<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>AddyOsmani.com &#124; Where User Interface Ideas Grows &#187; file store</title>
	<atom:link href="http://addyosmani.com/blog/tag/file-store/feed/" rel="self" type="application/rss+xml" />
	<link>http://addyosmani.com/blog</link>
	<description>This is the home of Addy Osmani (Web Developer, Designer &#38; Author). Here you can find some great tips and tutorials on everything to do with web development and even a few useful code samples!</description>
	<lastBuildDate>Fri, 03 Sep 2010 21:35:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Offline Cross-Browser Client-Side Storage for the Web using JavaScript and a little Flash</title>
		<link>http://addyosmani.com/blog/offline-cross-browser-client-side-storage-for-the-web-using-javascript-and-a-little-flash/</link>
		<comments>http://addyosmani.com/blog/offline-cross-browser-client-side-storage-for-the-web-using-javascript-and-a-little-flash/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 03:46:37 +0000</pubDate>
		<dc:creator>Addy</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[client-side]]></category>
		<category><![CDATA[client-side storage]]></category>
		<category><![CDATA[clientside]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[cross-browser]]></category>
		<category><![CDATA[file store]]></category>
		<category><![CDATA[firefox localstorage]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[flash storage]]></category>
		<category><![CDATA[google gears]]></category>
		<category><![CDATA[googlegears]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[html5 localstore]]></category>
		<category><![CDATA[html5 sql]]></category>
		<category><![CDATA[html5 storage]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[local storage space]]></category>
		<category><![CDATA[localstorage]]></category>
		<category><![CDATA[offline]]></category>
		<category><![CDATA[offline client-side storage]]></category>
		<category><![CDATA[offline storage]]></category>
		<category><![CDATA[safari]]></category>
		<category><![CDATA[settings storage]]></category>
		<category><![CDATA[storage]]></category>
		<category><![CDATA[storage offline]]></category>
		<category><![CDATA[store files locally]]></category>
		<category><![CDATA[web storage]]></category>
		<category><![CDATA[website files local]]></category>
		<category><![CDATA[website storage]]></category>

		<guid isPermaLink="false">http://addyosmani.com/blog/offline-cross-browser-client-side-storage-for-the-web-using-javascript-and-a-little-flash/</guid>
		<description><![CDATA[&#160; Hi guys. Today I&#8217;m going to show you how to do persistent Client-side storage that&#8217;ll work in any Web Browser without needing to use Cookies, Browser-Specific hacks or HTML5 &#8211; in other words, we&#8217;re going to store as much custom information as a site needs on a user&#8217;s system without needing to worry about [...]]]></description>
			<content:encoded><![CDATA[<p><a class="thickbox" href="http://addyosmani.com/blog/wp-content/uploads/2009/10/client.jpg"><img border="0" title="client" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="client" src="http://addyosmani.com/blog/wp-content/uploads/2009/10/client_thumb.jpg" /></a>&nbsp;</p>
<p>Hi guys. Today I&rsquo;m going to show you how to do <strong>persistent Client-side storage</strong> that&rsquo;ll work in any Web Browser <strong>without</strong> needing to use Cookies, Browser-Specific hacks or HTML5 &ndash; in other words, we&rsquo;re going to store as much custom information as a site needs on a user&rsquo;s system without needing to worry about compatibility issues.</p>
<p><span id="more-186"></span></p>
<p>&nbsp;</p>
<p>The reason we&rsquo;re interested in doing this is because it has a huge potential to free up database resources if we don&rsquo;t need to be saving information there &#8211; instead it can be readily loaded from our users computer through client-side storage. Even if you <strong>need</strong> to save data, you can always store it on your user&rsquo;s system and log it to the server it at a later date in the week.</p>
<p>&nbsp;</p>
<p>The inspiration behind this article was research I was putting into discovering the best way to achieve offline client-side storage using FireFox&rsquo;s <a href="http://hacks.mozilla.org/2009/06/localstorage/">LocalStorage</a>, HTML5&rsquo;s <a href="http://webkit.org/blog/126/webkit-does-html5-client-side-database-storage/">local databases</a> and Chrome&rsquo;s <a href="http://gears.google.com/">Google Gears</a>. Projects such as <a href="http://pablotron.org/?cid=1557">PersistJS</a> have tried to provide a pack that allows you to switch between any of these for your storage options (depending on what browser you have) but even then.. he problem has always been that there wasn&rsquo;t <strong>one solution</strong> that works well across all platforms and browsers&hellip;lets dive in and see if we can address that.</p>
<p>&nbsp;</p>
<p><a class="thickbox" href="http://addyosmani.com/blog/wp-content/uploads/2009/10/1255932843_yahoo.png"><img width="128" height="128" border="0" align="left" title="1255932843_yahoo" style="border-width: 0px; margin: 0px 20px 0px 0px; display: inline;" alt="1255932843_yahoo" src="http://addyosmani.com/blog/wp-content/uploads/2009/10/1255932843_yahoo_thumb.png" /></a></p>
<p>Our solution today is going to make use of a little-used YUI component created called <a href="http://developer.yahoo.com/yui/examples/swfstore/swfstore-advanced-example.html">SWFStore</a>. SWFStore allows you to store and access data in the Flash data store through a brilliant object-oriented JavaScript wrapper that makes it very straight-forward to add, update or remove data through your JavaScript code. It&rsquo;s clean and works very very well. This isn&rsquo;t the first time this method of storage has been tried, but the reason I chose to use SWFStore as the basis of this solution is because it offers a clean-way to extend how much data a site can store. For anyone that&rsquo;s aware of how Flash manages data, there&rsquo;s a basic limit of <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager.html#117152">100KB</a> per-domain imposed when you first start using it. SWFStore can however help you to easily <strong>prompt </strong>users to extend their Flash storage space and after that you&rsquo;re able to store as much data as you would like locally [<a href="http://developer.yahoo.com/yui/examples/swfstore/swfstore-settings-example_source.html">see advanced demo here</a>]</p>
<p>&nbsp;</p>
<p>I <strong>extended </strong>SWFStore using just a few functions so that I could easily save and retrieve data anywhere in the DOM tree. What I was able to do (and what you&rsquo;ll learn to do by the end of this article) is store any number of variables, text, html, data or objects for a site and load them up every time <strong>without needing to touch SQL</strong>. Using SWFStore was so straight-forward that I was even able to store all the reference data for a Google Calendar-like app locally, but let&rsquo;s get through some of the basics <img src='http://addyosmani.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&nbsp;</p>
<p><strong><font size="4">Demo and Tutorial</font></strong></p>
<p>&nbsp;</p>
<p><a class="thickbox" href="http://addyosmani.com/blog/wp-content/uploads/2009/10/image15.png"><img width="391" height="244" border="0" title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://addyosmani.com/blog/wp-content/uploads/2009/10/image_thumb14.png" /></a></p>
<p>&nbsp;</p>
<p>Before we look at any code, I think it&rsquo;s always useful to show a <strong>demo</strong> of what we&rsquo;re going to be building. <a href="http://www.addyosmani.com/resources/swfstore/examples/swfstore/test.html"><strong>Here</strong></a> I&rsquo;ve created a simple YUI app that allows you to save some <strong>sample data</strong> about a user to their local Flash data cache using JavaScript. This data includes <em>a nickname, custom background-image</em>, <em>reminder note</em>, <em>avatar, last page viewed on the site, hypothetical theme </em>and more.</p>
<p>&nbsp;</p>
<p>To help visualize the variables we&rsquo;re using a YUI DataTable in our page too and this is what the data looks like when populated inside:</p>
<p>&nbsp;</p>
<p><a class="thickbox" href="http://addyosmani.com/blog/wp-content/uploads/2009/10/image16.png"><img width="528" height="190" border="0" title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://addyosmani.com/blog/wp-content/uploads/2009/10/image_thumb15.png" /></a></p>
<p>&nbsp;</p>
<p>In the <strong>default view</strong> you&rsquo;re presented with a welcome Guest screen that uses the page&rsquo;s default settings. After you&rsquo;ve <strong>saved the sample data</strong> however, reload the page and you will see that every time you go back to it..your custom settings are now being used to render the modal window&rsquo;s data the way you &lsquo;chose&rsquo;. This could be taken further to render the page with different css, widgets or other elements depending on what the user wants, but for now this is enough to illustrate the concept.</p>
<p>&nbsp;</p>
<p>To use the SWFStore, include the following source files in your web page:</p>
<p>&nbsp;</p>
<p><font face="Courier" color="#804000"><strong>Dependencies</strong>&nbsp; <br />
&lt;script type=&quot;text/javascript&quot; src=&quot;</font><a href="http://yui.yahooapis.com/2.8.0r4/build/yahoo/yahoo.js&quot;"><font face="Courier" color="#804000">http://yui.yahooapis.com/2.8.0r4/build/yahoo/yahoo.js&quot;</font></a><font face="Courier" color="#804000">&gt;</font></p>
<p><font face="Courier" color="#804000">&lt;/script&gt;&nbsp; <br />
&lt;script type=&quot;text/javascript&quot; src=&quot;</font><a href="http://yui.yahooapis.com/2.8.0r4/build/dom/dom.js&quot;"><font face="Courier" color="#804000">http://yui.yahooapis.com/2.8.0r4/build/dom/dom.js&quot;</font></a><font face="Courier" color="#804000">&gt;</font></p>
<p><font face="Courier" color="#804000">&lt;/script&gt; </font></p>
<p><font face="Courier" color="#804000"></p>
<p>
<strong>Source files</strong><br />
&lt;script type=&quot;text/javascript&quot; src=&quot;</p>
<p><a href="http://yui.yahooapis.com/2.8.0r4/build/swfstore/swfstore.js&quot;"><font face="Courier" color="#804000">http://yui.yahooapis.com/2.8.0r4/build/swfstore/swfstore.js&quot;</font></a><font face="Courier" color="#804000">&gt;</font></font></p>
<p><font face="Courier" color="#804000">&lt;/script&gt;</font></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>By default, the file swfstore.swf is expected in the same directory as the HTML page in which a SWFStore Utility instance will appear. You must place a copy of the SWF on your server.</p>
<p>&nbsp;</p>
<p>To get started with the SWFStore, begin by placing it on the page. Create a &lt;div&gt; (or other element) placeholder into which you&rsquo;re able to render your SWFStore instance. In a usual use cases, you can set the width and height of the container to 0, since the SWFStore is a purely functional component and doesn&rsquo;t have it&rsquo;s own UI (except when your users want to request more storage space from Flash):</p>
<p>&nbsp;</p>
<p>&nbsp;<font face="Courier" color="#804000">&nbsp;&nbsp; &lt;div id=&quot;toBeReplaced&quot; style=&quot;width:0px;height:0px&quot;&gt;&lt;br /&gt;      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sorry guys! We&rsquo;re unable to load Flash content. The YUI SWFStore Utility requires Flash Player 9.0.115 or higher. &lt;br /&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;/div&gt;</font></p>
<p>&nbsp;</p>
<p>Then, instantiate the SWFStore by passing the id of this container &lt;div&gt; to it:</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; <font face="Courier" color="#804000">var swfstore = new YAHOO.util.SWFStore( &quot;toBeReplaced&quot; );</font></p>
<p>&nbsp;</p>
<p>The demo I created consists of two text fields, a few Buttons and a DataTable as well as a modal window. The Buttons let you save data, set some sample information to store, set properties on SWFStore, or clear all items from the data store.</p>
<p>&nbsp;</p>
<p><a class="thickbox" href="http://addyosmani.com/blog/wp-content/uploads/2009/10/image17.png"><img width="419" height="233" border="0" title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://addyosmani.com/blog/wp-content/uploads/2009/10/image_thumb16.png" /></a></p>
<p>&nbsp;</p>
<p>Once the page has been loaded up, the initialize() function is called to instantiate a SWFStore instance and set up some listeners. To be safe, we also disable all of the Buttons until the SWFStore is ready &ndash; good UI practices always come in handy.</p>
<p>&nbsp;</p>
<p>&nbsp;<font face="Courier" color="#804000">&nbsp;&nbsp; function initialize()      <br />
&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp; var useCompression = compressionCheckbox.get(&quot;checked&quot;);       <br />
&nbsp;&nbsp;&nbsp; saveButton.set(&quot;disabled&quot;, true); </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; setButton.set(&quot;disabled&quot;, true);      <br />
&nbsp;&nbsp;&nbsp; purgeButton.set(&quot;disabled&quot;, true);       <br />
&nbsp;&nbsp;&nbsp; removeButton.set(&quot;disabled&quot;, true);       <br />
&nbsp;&nbsp;&nbsp; removeAtButton.set(&quot;disabled&quot;, true);       <br />
&nbsp;&nbsp;&nbsp; sharedataCheckbox.set(&quot;disabled&quot;, true);&nbsp; <br />
&nbsp;&nbsp;&nbsp; compressionCheckbox.set(&quot;disabled&quot;, true); </font></p>
<p>
<font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; //the swfstore instance </font></p>
<p>
<font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; swfstore = new YAHOO.util.SWFStore(&quot;swfstoreContainer&quot;, false, useCompression); </font></p>
<p>
<font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; //some basic listeners for user feedback      <br />
&nbsp;&nbsp;&nbsp; swfstore.addListener(&quot;save&quot;, onSave);       <br />
&nbsp;&nbsp;&nbsp; swfstore.addListener(&quot;error&quot;, onError);       <br />
&nbsp;&nbsp;&nbsp; swfstore.addListener(&quot;quotaExceededError&quot;, onError);       <br />
&nbsp;&nbsp;&nbsp; swfstore.addListener(&quot;securityError&quot;, onError);       <br />
&nbsp;&nbsp;&nbsp; swfstore.addListener(&quot;contentReady&quot;, onContentReady);</font></p>
<p>&nbsp;</p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; //extended listeners</font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp; swfstore.addListener(&quot;set&quot;, onSet);</font>&nbsp;</p>
<p>&nbsp;</p>
<p>When SWFStore is ready, it will dispatch a contentReady event. We can then enable the Buttons and initialize a DataTable with any previously stored values. Because items are stored as objects, we need to loop through them to turn them into name-value pairs suitable for use with the DataTable.</p>
<p>
&nbsp;<font face="Courier" color="#804000">&nbsp;&nbsp; function onContentReady(event)      <br />
&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; saveButton.set(&quot;disabled&quot;, false);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; purgeButton.set(&quot;disabled&quot;, false);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; removeButton.set(&quot;disabled&quot;, false);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; removeAtButton.set(&quot;disabled&quot;, false);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sharedataCheckbox.set(&quot;disabled&quot;, false);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compressionCheckbox.set(&quot;disabled&quot;, false); </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setButton.set(&quot;disabled&quot;, false);      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; load();       <br />
&nbsp;&nbsp;&nbsp; } </font></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><font face="Courier" color="#804000">//next we define default values for the variables we load when the page is opened</font></p>
<p>&nbsp;</p>
<p><font size="2" face="Courier" color="#804000">&nbsp; var layout = &quot;Default&quot;;</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp; var fontname = &quot;Verdana&quot;;</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp; var friendlyname = &quot;Guest&quot;;</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp; var windowSize = &quot;400px&quot;</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp; var reminder1 = &quot;No reminders set&quot;;</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp; var avatarURL =&nbsp;&nbsp; &quot;http://www.addyosmani.com/resources/swfstore/examples/</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp; swfstore/default.png&quot;;</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp; var lastViewed = &quot;&quot;;</font></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; function load()      <br />
&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //could use swfstore.getItems(), but that would not separate the data into fields </font></p>
<p>&nbsp;</p>
<p><font face="Courier" color="#804000">var settingName = null;</font></p>
<p><font face="Courier" color="#804000">var settingValue = null;</font></p>
<p><font face="Courier" color="#804000">var len = swfstore.getLength();</font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var arr = []; </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; len; i++)      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arr.push({ name:swfstore.getNameAt(i), value: swfstore.getValueAt(i) }) </font></p>
<p>&nbsp;</p>
<p><font size="2" face="Courier" color="#804000">settingName = swfstore.getNameAt(i);</font></p>
<p><font size="2" face="Courier" color="#804000">settingValue = swfstore.getValueAt(i);</font></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><font size="2" face="Courier" color="#804000">//here we use a switch statement to check the value loaded from the data-table. We are then able to assign it to a more easy to remember variable name and read it anywhere in the DOM</font></p>
<p>&nbsp;</p>
<p><font size="2" face="Courier" color="#804000">switch(settingName)</font></p>
<p><font size="2" face="Courier" color="#804000">{</font></p>
<p><font size="2" face="Courier" color="#804000">case &#8216;layout&#8217;:</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; layout = settingValue;</font></p>
<p><font size="2" face="Courier" color="#804000">break;</font></p>
<p><font size="2" face="Courier" color="#804000">case &#8216;font&#8217;:</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fontname = settingValue;</font></p>
<p><font size="2" face="Courier" color="#804000">break;</font></p>
<p><font size="2" face="Courier" color="#804000">case &#8216;friendlyName&#8217;:</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; friendlyname = settingValue;</font></p>
<p><font size="2" face="Courier" color="#804000">break;</font></p>
<p><font size="2" face="Courier" color="#804000">case &#8216;windowSize&#8217;:</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; windowSize = settingValue;</font></p>
<p><font size="2" face="Courier" color="#804000">break;</font></p>
<p><font size="2" face="Courier" color="#804000">case &#8216;backgroundImage&#8217;:</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; backgroundImage = settingValue;</font></p>
<p><font size="2" face="Courier" color="#804000">break;</font></p>
<p><font size="2" face="Courier" color="#804000">case &#8216;reminder1&#8242;:</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reminder1 = settingValue;</font></p>
<p><font size="2" face="Courier" color="#804000">break;</font></p>
<p><font size="2" face="Courier" color="#804000">case &#8216;avatarURL&#8217;:</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; avatarURL = settingValue;</font></p>
<p><font size="2" face="Courier" color="#804000">break;</font></p>
<p><font size="2" face="Courier" color="#804000">case &#8216;lastViewed&#8217;:</font></p>
<p><font size="2" face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastViewed = settingValue;</font></p>
<p><font size="2" face="Courier" color="#804000">break;</font></p>
<p><font size="2" face="Courier" color="#804000">}</font></p>
<p><font face="Courier" color="#804000"></p>
<p>
<font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </font></p>
<p>&nbsp;</p>
<p></font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var datasource = new YAHOO.util.LocalDataSource(arr); </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; datasource.responseSchema = {fields : [&quot;name&quot;, &quot;value&quot;]}; </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var configs =      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scrollable: true       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var columns =      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {key:&quot;name&quot;, label:&quot;Storage Name (Key)&quot;},       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {key:&quot;value&quot;, label:&quot;Text Stored&quot;}       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ]; </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; datatable = new YAHOO.widget.DataTable(&quot;datatableContainer&quot;, columns, datasource, configs); </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; } </font></p>
<p>&nbsp;</p>
<p><a class="thickbox" href="http://addyosmani.com/blog/wp-content/uploads/2009/10/image18.png"><img width="465" height="148" border="0" title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://addyosmani.com/blog/wp-content/uploads/2009/10/image_thumb17.png" /></a></p>
<p>The &ldquo;Set Test Data&rdquo; button allows you to set some test data (or any information) from a function or the rest of your UI to save into the data store. In the demo, I&rsquo;ve chosen to store some data for a fake user profile application that is loaded up and used by a modal window to demonstrate just how easy this is to use through JavaScript. To save an item call <strong>swfstore.setItem(variableName, variableValue). </strong></p>
<p>&nbsp;</p>
<p><font size="2" face="Courier" color="#804000">function set()</font></p>
<p><font size="2" face="Courier" color="#804000">{</font></p>
<p><font size="2" face="Courier" color="#804000">swfstore.setItem(&#8216;layout&#8217;, &#8216;helio&#8217;);</font></p>
<p><font size="2" face="Courier" color="#804000">swfstore.setItem(&#8216;font&#8217;, &#8216;tahoma&#8217;);</font></p>
<p><font size="2" face="Courier" color="#804000">swfstore.setItem(&#8216;friendlyName&#8217;, &#8216;John Smith&#8217;);</font></p>
<p><font size="2" face="Courier" color="#804000">swfstore.setItem(&#8216;windowSize&#8217;, &#8217;500px&#8217;);</font></p>
<p><font size="2" face="Courier" color="#804000">swfstore.setItem(&#8216;backgroundImage&#8217;, &#8216;http://farm3.static.flickr.com/2363/2085145159_85bd6d7be1_o.jpg&#8217;);</font></p>
<p><font size="2" face="Courier" color="#804000">swfstore.setItem(&#8216;reminder1&#8242;, &#8216;Feed the Cat today!&#8217;);</font></p>
<p><font size="2" face="Courier" color="#804000">swfstore.setItem(&#8216;avatarURL&#8217;, &#8216;http://www.addyosmani.com/resources/swfstore/examples/</font></p>
<p><font size="2" face="Courier" color="#804000">sswfstore/avatar.png&#8217;);</font></p>
<p><font size="2" face="Courier" color="#804000">swfstore.setItem(&#8216;lastViewed&#8217;, lastViewed);</font></p>
<p><font size="2" face="Courier" color="#804000">alert(&quot;Refresh this page to apply the new saved settings&quot;);</font></p>
<p><font size="2" face="Courier" color="#804000">}</font></p>
<p>&nbsp;</p>
<p>Similarly, the &quot;Save&quot; Button is set up to take the values from the text fields in our app and store them, using this function.</p>
<p>&nbsp;</p>
<p>&nbsp;<font color="#804000">&nbsp;&nbsp; function save()      <br />
&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swfstore.setItem(&nbsp; YAHOO.util.Dom.get(&#8216;nameField&#8217;).value, YAHOO.util.Dom.get(&#8216;valueField&#8217;).value);       <br />
&nbsp;&nbsp;&nbsp; }       <br />
</font></p>
<p>&nbsp;</p>
<p>Some of the other Buttons are set up to remove items from storage and are useful for cases where you would like to make sure all the local data for a site has been deleted.</p>
<p>&nbsp;</p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; function remove()      <br />
&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var obj = YAHOO.util.Dom.get(&#8216;nameField&#8217;).value;       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swfstore.removeItem(obj); </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; } </font></p>
<p>&nbsp;</p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; function removeItemAt()      <br />
&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var index = parseInt(YAHOO.util.Dom.get(&#8216;indexField&#8217;).value);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swfstore.removeItemAt(index); </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; } </font></p>
<p>&nbsp;</p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp; function purge()      <br />
&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swfstore.clear();       <br />
&nbsp;&nbsp;&nbsp; } </font></p>
<p>&nbsp;</p>
<p>We&#8217;ve already set up listeners for the &quot;save&quot; and &ldquo;set&rdquo; events, which are displayed for when each of their respective buttons are clicked. The onSet event loops through rows of the DataTable and either adds rows, deletes them or updates values.</p>
<p>&nbsp;</p>
<p><font size="2" face="Courier" color="#804000">function onSet(event)</font></p>
<p><font size="2" face="Courier" color="#804000">{</font></p>
<p><font size="2" face="Courier" color="#804000">var newobj = {name: event.key, value: event.newValue};</font></p>
<p><font size="2" face="Courier" color="#804000">var len = datatable.getRecordSet().getLength();</font></p>
<p><font size="2" face="Courier" color="#804000">//loop through current records and see if this has been added before</font></p>
<p><font size="2" face="Courier" color="#804000">for (var i = 0; i &lt; len; i++ )</font></p>
<p><font size="2" face="Courier" color="#804000">{</font></p>
<p><font size="2" face="Courier" color="#804000">var rec = datatable.getRecord(i);</font></p>
<p><font size="2" face="Courier" color="#804000">var data = rec.getData();</font></p>
<p><font size="2" face="Courier" color="#804000">//if it&#8217;s been added already, update it</font></p>
<p>&nbsp;</p>
<p><font size="2" face="Courier" color="#804000">if(data.name == event.key)</font></p>
<p><font size="2" face="Courier" color="#804000">{</font></p>
<p><font size="2" face="Courier" color="#804000">datatable.updateRow(i, newobj);</font></p>
<p><font size="2" face="Courier" color="#804000">return;</font></p>
<p><font size="2" face="Courier" color="#804000">}</font></p>
<p><font size="2" face="Courier" color="#804000">}</font></p>
<p><font size="2" face="Courier" color="#804000">//if it&#8217;s not been added, add it</font></p>
<p><font size="2" face="Courier" color="#804000">datatable.addRow(newobj);</font></p>
<p><font size="2" face="Courier" color="#804000">}</font></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>The onSave function is very similar to onSet except it&rsquo;s more constricted to the UI controls in this demo whilst onSet and the &ldquo;set&rdquo; method are more open to being called from anywhere in your code and storing your data.</p>
<p>&nbsp;</p>
<p>&nbsp; <font face="Courier" color="#804000">&nbsp; function onSave(event)      <br />
&nbsp;&nbsp;&nbsp; { </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //added      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(event.info == &quot;add&quot; || event.info == &quot;update&quot;)       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var newobj = {name: event.key, value: event.newValue}; </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var len = datatable.getRecordSet().getLength(); </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //loop through current records and see if this has been added before      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; len; i++ )       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var rec = datatable.getRecord(i);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var data = rec.getData(); </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //if it&#8217;s been added already, update it      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(data.name == event.key)       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; datatable.updateRow(i, newobj);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //if it&#8217;s not been added, add it      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; datatable.addRow(newobj);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //removed      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(event.info == &quot;delete&quot;)       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //var index = parseInt(YAHOO.util.Dom.get(&#8216;indexField&#8217;).value);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; datatable.deleteRow(event.index);       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </font></p>
<p><font face="Courier" color="#804000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //cleared      <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; datatable.deleteRows(0, datatable.getRecordSet().getLength());       <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }       <br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p>&nbsp;</p>
<p>And that&rsquo;s it!</p>
<p>&nbsp;</p>
<p>Most of you will know me as being a huge jQuery fan (and I&rsquo;m certain most of this work can be ported to the framework) but as a concept I thought it was very interesting that cross-browser client-side storage could be achieved <em>without </em>needing to use add-ons like Gears or have a browser following the latest trends in computing.</p>
<p>&nbsp;</p>
<p><a class="thickbox" href="http://addyosmani.com/blog/wp-content/uploads/2009/10/image19.png"><img width="354" height="247" border="0" title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://addyosmani.com/blog/wp-content/uploads/2009/10/image_thumb18.png" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>The methods I&rsquo;ve described above <em>already</em> work in FireFox, Chrome and even IE6!, so it&rsquo;s feasible for you to start using them <strong>today</strong>.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>To <strong>download</strong> YUI with the above <strong>demo</strong> integrated into it, click <a href="http://www.addyosmani.com/resources/downloads/swfstore.rar">here</a>.</p>
<p>&nbsp;</p>
<p>Thanks and I hope this post was useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://addyosmani.com/blog/offline-cross-browser-client-side-storage-for-the-web-using-javascript-and-a-little-flash/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
