<?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>Jens Arps &#187; Goodies to go</title>
	<atom:link href="http://jensarps.de/category/goodies-to-go/feed/" rel="self" type="application/rss+xml" />
	<link>http://jensarps.de</link>
	<description></description>
	<lastBuildDate>Fri, 25 Nov 2011 16:16:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Working with IDBWrapper, Part 1</title>
		<link>http://jensarps.de/2011/11/25/working-with-idbwrapper-part-1/</link>
		<comments>http://jensarps.de/2011/11/25/working-with-idbwrapper-part-1/#comments</comments>
		<pubDate>Fri, 25 Nov 2011 16:16:34 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Goodies to go]]></category>
		<category><![CDATA[How to]]></category>
		<category><![CDATA[Storage]]></category>
		<category><![CDATA[client-side storage]]></category>
		<category><![CDATA[IDB]]></category>
		<category><![CDATA[IndexedDB]]></category>
		<category><![CDATA[persistence]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=405</guid>
		<description><![CDATA[A while ago I released IDBWrapper. If you don&#8217;t know it, it&#8217;s a wrapper for IndexedDB, a current specification (in draft status) for an in-browser object store. It&#8217;s implemented in Firefox and Chrome, and somehow (as a plugin of sorts) also in IE, but, honestly, I don&#8217;t care about that too much. It is mainly [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I released <a href="https://github.com/jensarps/IDBWrapper" target="_blank">IDBWrapper</a>. If you don&#8217;t know it, it&#8217;s a wrapper for <a href="http://www.w3.org/TR/IndexedDB/" target="_blank">IndexedDB</a>, a current specification (in draft status) for an in-browser object store. It&#8217;s implemented in Firefox and Chrome, and <a href="http://html5labs.interoperabilitybridges.com/prototypes/indexeddb/indexeddb/info" target="_blank">somehow</a> (as a plugin of sorts) also in IE, but, honestly, I don&#8217;t care about that too much.</p>
<p>It is mainly meant to serve as an example implementation, so that you could have a look at the code and see how to work with IndexedDB. But I figured that people are also interested in actually using it, as it abstracts away many of the tedious internals of IndexedDB (like transactions) – and it is perfectly fine to use IDBWrapper for all non-overly-complex scenarios.</p>
<p>So here&#8217;s a tutorial about how to work with IDBWrapper and add a little background info about IndexedDB internals every now and then, instead of writing Yet-Another-Super-Technical-IDB-Blargh. Part one will cover some info about what IndexedDB is, getting IDBWrapper to run and how to read and write data to a store. Part two will be about querying the store.</p>
<p><span id="more-405"></span></p>
<h1>What is IndexedDB – why is it special?</h1>
<p>IndexedDB really differs from other client-side storage engines. It&#8217;s an ObjectStore, whereas localStorage is a key-value store and Sqlite is a relational database. Think of it as a database like those SQL thingies, but with more freedom but without a query language. Uh, roughly, yeah. You store and retrieve JavaScript objects (unlike localStorage) and you don&#8217;t have fixed tables with predefined columns and types (unlike Sqlite).</p>
<h1>Getting IDBWrapper</h1>
<p>You can <a href="https://github.com/jensarps/IDBWrapper/" target="_blank">download/clone/fork IDBWrapper at GitHub</a>. To include it in your page/project, you have two options: You can either include the IDBStore.js file via a script tag, or you can require it using an AMD loader like RequireJS.</p>
<h1>Let&#8217;s go!</h1>
<p>In this tutorial, we&#8217;ll create a people store where we store information about humans – a group of customers, for example.</p>
<p>&nbsp;</p>
<p><strong>Step one: open the store</strong><br />
<script type="text/javascript" src="https://gist.github.com/1391434.js"></script>A note on the properties we pass to the constructor:</p>
<ul>
<li>dbName, dbDescription, storeName: just choose meaningful names</li>
<li>dbVersion: start with &#8217;1.0&#8242;, and only change this when the structure of your db/store changes</li>
<li>keyPath: the property you want as unique primary key</li>
<li>autoIncrement: set this to true if you do not want to take care of the uniqueness of the primary key yourself</li>
<li>onStoreReady: a function to be called when your store is ready to work with</li>
</ul>
<p>&nbsp;</p>
<p>IDBwrapper will open the database, check if a store with the given name exists and if not, it will create it using the above properties. You&#8217;ll then get an IDBStore instance back that you can use to work with the store. Once the store is created, it&#8217;s persistent. But, if you need to delete and re-create it (for example, if you happened to pick the wrong value for keyPath), you can delete the store using the <code>deleteObjectStore</code> method.</p>
<p><em>Inside IndexedDB</em>: IDBWrapper works with one store; when you do a <code>new IDBStore()</code> it represents one store in an IndexedDB. If you want multiple stores inside of the same IndexedDB, you&#8217;d have to do a <code>new IDBStore()</code> for each store. This is an artificial limitation of IDBWrapper; if you work with IndexedDB directly, you can lock multiple stores when starting a transaction. This be useful when you want to update one store depending on the information found in another store, and you want to prevent this other store&#8217;s contents to change during your update action.</p>
<p>&nbsp;</p>
<p><strong>Step 2: storing a customer</strong><br />
<script type="text/javascript" src="https://gist.github.com/1391487.js?file=turorial.js"></script></p>
<p>Note how we don&#8217;t have an <code>id</code> property on the dude object, as we specified autoIncrement as true, so the database will take care of this. In the <code>onsuccess</code> callback we&#8217;ll get the id of the newly inserted record back. Also, see how we attached an array of emails to the record? In a relational database you&#8217;d set up a different table for email addresses – no need to do that in IndexedDB.</p>
<p><em>Inside IndexedDB</em>: Make sure to wait until the store is ready before operating on it! The whole nature of IndexedDB is asynchronous. Whatever you do, you will have to work with callbacks. There is, however, also a draft for a specification of a synchronous API, but that is not implemented in any browser (and I don&#8217;t think this is going to happen anytime soon).</p>
<p>&nbsp;</p>
<p><strong>Step 3: reading the customer back from the store</strong><br />
<script type="text/javascript" src="https://gist.github.com/1391509.js?file=tutorial.js"></script></p>
<p>We just pass the id we got after inserting to the get method, and there we have our record from the store. It&#8217;s exactly the same thing we stored earlier, with one exception: the object now has the <code>id</code> property which has been attached to it by the database.</p>
<p><em>Inside IndexedDB</em>: What we pass as first parameter to the <code>get</code> method is the <em>keyPath value</em>. That means when we pass 1 to it, the database will look for an object that has 1 as value in it&#8217;s keyPath property, which we set to &#8216;id&#8217; when we created the store.</p>
<p>&nbsp;</p>
<p><strong>Step 4: updating data</strong><br />
<script src="https://gist.github.com/1393216.js?file=turorial.js"></script></p>
<p>To update a record, you also use the put method: If there already is an object in the store with the same keyPath value (the id), it will simply overwrite it. Note that it will really, really overwrite the existing object, which means you cannot simply put a modified property of it, but have to put the whole object, including all properties.</p>
<p><em><strong>Inside IndexedDB</strong></em>: keyPath values are also Type-sensitive. That means, if the id of our dude is 1 and of type Number, you have to pass numeric 1 to the get method to retrieve the dude, and for updates the value of the id property needs to be numeric 1. If you use &#8220;1&#8243; as String, IndexedDB will think of it as a different value.</p>
<p>&nbsp;</p>
<p><strong>Step 5: getting all items</strong><br />
<script src="https://gist.github.com/1393243.js?file=tutorial.js"></script></p>
<p>Nothing really to say about it. Just one note: IDBStore has default error handlers for every async method that prints potential errors to the console. So if you&#8217;re just playing around you don&#8217;t need to pass your own handler to the methods.</p>
<p>&nbsp;</p>
<p><strong>Step 6: deleting an item</strong><br />
<script src="https://gist.github.com/1393271.js?file=tutorial.js"></script></p>
<p>Different browsers and versions return different values to the success callback; that&#8217;s why there is an extra check in the success callback.</p>
<p>&nbsp;</p>
<p><strong>Step 7: clearing the store</strong><br />
<script src="https://gist.github.com/1393287.js?file=tutorial.js"></script></p>
<p>If you need to clear the store from all stored entries, you can use the clear method. Note that this won&#8217;t reset Chrome&#8217;s autoIncrement counter.</p>
<h1>That&#8217;s it, thanks for listening!</h1>
<p>Now you know everything to do basic IndexedDB data operations with IDBWrapper. Make sure to check out the examples and the documentation!</p>
<p>Part two of this tutorial about querying the store will follow soon.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="https://github.com/jensarps/IDBWrapper" target="_blank">IDBWrapper on GitHub</a></li>
<li><a href="https://github.com/jensarps/IDBWrapper/blob/master/README.md" target="_blank">IDBWrapper Documentation</a></li>
<li><a href="http://jensarps.github.com/IDBWrapper/example/" target="_blank">IDBWrapper Examples</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2011/11/25/working-with-idbwrapper-part-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creating a persistent Dojo Object Store</title>
		<link>http://jensarps.de/2011/04/27/creating-a-persistent-dojo-object-store/</link>
		<comments>http://jensarps.de/2011/04/27/creating-a-persistent-dojo-object-store/#comments</comments>
		<pubDate>Wed, 27 Apr 2011 16:30:49 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Dojo Love]]></category>
		<category><![CDATA[Goodies to go]]></category>
		<category><![CDATA[How to]]></category>
		<category><![CDATA[Storage]]></category>
		<category><![CDATA[client-side storage]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[StorageJS]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=288</guid>
		<description><![CDATA[[Note: This is a cross-post. I also published this on the uxebu blog.]As of version 1.6, dojo comes with the new Dojo Object Store API. This is an awesome thing, as it greatly simplifies the work with data stores in Dojo. Everybody who had to do with the traditional dojo.data API felt it was overly [...]]]></description>
			<content:encoded><![CDATA[<p>[<em>Note: This is a cross-post. I also published this on the <a href="http://uxebu.com/blog/2011/04/27/creating-a-persistent-dojo-object-store/" target="_blank">uxebu blog</a>.</em>]</p><p>As of version 1.6, dojo comes with the new <a href="http://docs.dojocampus.org/dojo/store" target="_blank">Dojo Object Store API</a>. This is an awesome thing, as it greatly simplifies the work with data stores in Dojo. Everybody who had to do with the traditional dojo.data API felt it was overly complex and hard to use – this has finally changed now. There are also wrappers from and to the old and new APIs, so that you can do stuff like using your traditional data-aware widgets with a new Object Store. And the goodness doesn’t end here; but more on this later. If you haven’t done so yet, you might want to read the <a href="https://www.sitepen.com/blog/2011/02/15/dojo-object-stores/" target="_blank">excellent post on the new Dojo Object Stores</a> by Kris Zyp where he explains all the awesomeness he created.</p>
<p><span id="more-288"></span><br />
Dojo also comes with two fresh implementations for the API, a non-persistent memory store and a JsonRest store that interacts with a server through RESTful HTTP requests. You can also observe changes made to objects in the store. What is missing is a store that uses a client-side persistent backend, which would be useful for a couple of reasons (e.g., as one commenter in that post asks, to use it as chache store for dojo.store.Cache). As Kris already mentions, it’s a piece of cake to create one, so let’s go ahead and do it!</p>
<h2>Choosing the Backend</h2>
<p>The post mentions two possible candidates: dojox.storage and <a href="https://github.com/jensarps/StorageJS" target="_blank">StorageJS</a>, both already having a similar API, so making them compliant to the Dojo Object Store API is fairly easy. For this tutorial I choose StorageJS – because it is very lightweight and still provides all we need (and, well, for a couple of other reasons that don’t belong in this post). So, what is the exact API we need to comply to? Check it out <a href="http://docs.dojocampus.org/dojo/store#id2" target="_blank">in the docs</a>. See the first sentence in that paragraph? <em>“Every method in the API is optional, it’s presence indicating support for that feature.”</em> Wow, that’s nice!</p>
<h2>Basic compliance</h2>
<p>Let’s start with the methods get(), put(), add() and remove(). That will make our store pretty usable for most store scenarios.</p>
<p>First, create a ‘store’ object we can work with (StorageJS creates a global variable called <code class="codecolorer text mac-classic"><span class="text">storage</span></code> where all it’s methods reside):</p>
<p>‘store’ now contains everything that ‘storage’ does, but we can leave the original ‘storage’ object alone and modify our ‘store’ object if needed. Time for the first method, let’s start with <code class="codecolorer text mac-classic"><span class="text">get()</span></code>. StorageJS works with Strings as keys and values only, so we need to parse what we get from it.</p>
<p>Easy one, now move on to <code class="codecolorer text mac-classic"><span class="text">put()</span></code>. The Object Store API allows user to do stuff like this: <code class="codecolorer text mac-classic"><span class="text">store.put({foo: 'bar'}, {id: 3})</span></code> as well as <code class="codecolorer text mac-classic"><span class="text">store.put({id: 3, foo: 'bar'})</span></code>. Also, StorageJS only has the method set() instead of put() and add().</p>
<p>Easy, as well – you could write this as a one-liner. Now, <code class="codecolorer text mac-classic"><span class="text">add()</span></code>. It’s close to put, except that it won’t overwrite data that already exists. So we just need to check if something with the given id already exists and throw an error if so.</p>
<p>What about <code class="codecolorer text mac-classic"><span class="text">remove()</span></code>? Nothing to do there, it already has the desired signature and functionality.</p>
<p>That’s it, we’re done with basic compliance. Our ‘store’ object now implements the basic methods of the Dojo Object Store API and can be used by anything that can work with a Dojo Object Store – and it will keep it’s state persistent in the browser.</p>
<h2>More compliance? Querying!</h2>
<p>There’s one interesting thing in the API: the <code class="codecolorer text mac-classic"><span class="text">query()</span></code> method. Uh, yeah, we want that! Lucky us, Dojo already provides a query engine as well as a method that makes sure there are iterative methods and a <code class="codecolorer text mac-classic"><span class="text">total</span></code> property containing the number of hits available in our result (well, it also abstracts away the differences between sync and async results, but as StorageJS is purely synchronous, this is not important to us). First, define a queryEngine:</p>
<p>So, if we want our store to be able to run queries, all we need to do is to take the store’s data and hand it over to the query engine. We use StorageJS’ getAll() method to acquire the data. It will return an array of objects in the form { key: ‘theKey’, value: ‘theValue’}, but the queryEngine wants an array containing only the objects, so we need to do a conversion.</p>
<p>Now we can query our store for specific data, like so: <code class="codecolorer text mac-classic"><span class="text">var results = store.query({ prime: true });</span></code> This will give us all objects in the store that have a property called ‘prime’ and have that property set to true.</p>
<h2>Hierarchie and Transactions</h2>
<p>The API also mentions methods about data hierarchie and transactions, but I’m not going to cover these in this tutorial.</p>
<h2>Convenience and Optimization</h2>
<p>Currently, every time we run a query, we fetch all data again from our storage engine. So, if you don’t have a massive amount of data and want to query the store a lot, it might be wise to maintain a copy of all data in memory. There are other things you could optimize as well – or you could write your own queryEngine.</p>
<p>For your convenience,  <a href="http://statis.uxebu.com/~jens/dojo.store/PersistentLocal.js" target="_blank">here’s a wrapper</a> that creates a Dojo Object Store like we did above and accepts a useMemory parameter during instantiation that denotes whether a copy of the data should be kept in memory or not. It uses the traditional require/provide instead of the AMD format. If you want to use it, make sure you use the right namespace in the declare() call! (Or, not recommended, copy it in the /dojo/store directory.)</p>
<p>If you want to fool around with it in the console first, you can go <a href="http://static.uxebu.com/~jens/dojo.store/index-persistent-nomemory.html" target="_blank">here (non-memory-using)</a> or <a href="http://static.uxebu.com/~jens/dojo.store/index-persistent-usememory.html" target="_blank">here (memory-using)</a>, check out the source and fire up the console and try things out.</p>
<h2>Getting StorageJS</h2>
<p>The above code uses the features base and getAll, so you could do a specific build of StorageJS with these features or just <a href="https://github.com/jensarps/StorageJS/tree/master/builds?raw=true" target="_blank">grab a full build</a> of it for your desired storage engine (the storage-full-[engine].js files). If you don’t know about storage engines, all modern browser support localStorage, so <a href="https://github.com/jensarps/StorageJS/raw/master/builds/storage-full-localStorage.js" target="_blank">this is the one</a> what you might want.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2011/04/27/creating-a-persistent-dojo-object-store/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Encrypted client-side storage with dojo</title>
		<link>http://jensarps.de/2010/04/15/encrypted-client-side-storage-with-dojo/</link>
		<comments>http://jensarps.de/2010/04/15/encrypted-client-side-storage-with-dojo/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 21:48:54 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Dojo Love]]></category>
		<category><![CDATA[Experiments in Web]]></category>
		<category><![CDATA[Goodies to go]]></category>
		<category><![CDATA[Storage]]></category>
		<category><![CDATA[client-side storage]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[dojox]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[localStorage]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=248</guid>
		<description><![CDATA[A couple of days ago, Nicholas Zakas wrote an article about secure client side storage. I think the scenario he mentioned (working from a cyber cafe) is not unsafe by nature, and could be well handled by an application. Nonetheless, client side storage such as localStorage still is subject to DNS spoofing attacks (which is [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of days ago, <a href="http://www.twitter.com/slicknet/" target="_blank">Nicholas Zakas</a> wrote <a href="http://www.nczonline.net/blog/2010/04/13/towards-more-secure-client-side-data-storage/" target="_blank">an article</a> about secure client side storage. I think the scenario he mentioned (working from a cyber cafe) is not unsafe by nature, and could be well handled by an application. Nonetheless, client side storage such as <code>localStorage</code> still is subject to DNS spoofing attacks (which is the main security issue, I think). To handle this, one needs to encrypt the keys and values in the store.</p>
<p>So here you go: <code>dojox.storage.encrypted</code>, a <a href="http://en.wikipedia.org/wiki/Blowfish_%28cipher%29" target="_blank">Blowfish</a> encrypted storage. It sits on top of <code>dojox.storage</code>, and you get all the dojo storage manager goodness, mainly the automatic selection of the best storage provider available. It exposes the complete API that <code>dojox.storage</code> does. If an attacker gains access to the storage area, he can still nuke the storage, but the data found within will be useless.<br />
<span id="more-248"></span><br />
I&#8217;m not completely happy with it&#8217;s architecture, and I didn&#8217;t have the time yet to fully test it with all providers, but it works pretty well with <code>localStorage</code> and the performance is not too bad. If you have a spare minute and are interested, feel free to to test it yourself (ah I know, you don&#8217;t have the time yourself, but I&#8217;d be thankful!)…</p>
<h2>Usage</h2>
<p>Just use it as you would use dojox.storage, except that you need to set your passphrase before you start working with the storage:</p>
<pre>dojo.require("dojox.storage.encrypted");
var sto = dojox.storage.encrypted;
sto.setPassphrase("my super secret passphrase");
sto.put('key','value');
var value = sto.get('key');</pre>
<p>It uses/requires <code>dojox.encoding.crypto.Blowfish</code> but that&#8217;s been in dojo for ages, so no worries.</p>
<p>To use it, just put the <code>encrypted.js</code> file in your dojox/storage directory.</p>
<h2>Files</h2>
<p><a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/dojox/storage/encrypted.js" target="_blank">the code (encrypted.js)</a><br />
<a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/dojox/storage/tests/test_enc_storage.html">the test page</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2010/04/15/encrypted-client-side-storage-with-dojo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>persistent local storage with dojo</title>
		<link>http://jensarps.de/2010/01/04/persistent-local-storage-with-dojo/</link>
		<comments>http://jensarps.de/2010/01/04/persistent-local-storage-with-dojo/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 21:46:40 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Dojo Love]]></category>
		<category><![CDATA[Experiments in Web]]></category>
		<category><![CDATA[Goodies to go]]></category>
		<category><![CDATA[Storage]]></category>
		<category><![CDATA[client-side storage]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[dojox]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[local]]></category>
		<category><![CDATA[localStorage]]></category>
		<category><![CDATA[persistence]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=140</guid>
		<description><![CDATA[Last year, Brian Leroux&#8216;s Lawnchair caught my interest – it is an easy and fast way to access local persistant local storage. Uh, persistant local storage? Ahm, yeah, in case you don&#8217;t know, that means a client-side storage, be it in a browser, or in an Air app. It&#8217;s not very popular, but that concept [...]]]></description>
			<content:encoded><![CDATA[<p>Last year, <a href="http://twitter.com/brianleroux" target="_blank">Brian Leroux</a>&#8216;s <a href="http://brianleroux.github.com/lawnchair/" target="_blank">Lawnchair</a> caught my interest – it is an easy and fast way to access local persistant local storage.</p>
<p><strong>Uh, persistant local storage?</strong></p>
<p>Ahm, yeah, in case you don&#8217;t know, that means a client-side storage, be it in a browser, or in an Air app. It&#8217;s not very popular, but that concept has been around for a long time. So why local? There are two major reasons for it: First, we need this for apps and tools that work offline – and apps and tools that work online but need an offline backup and sync later. <a href="http://twitter.com/kriszyp" target="_blank">Kris Zyp</a> wrote a <a href="http://www.sitepen.com/blog/2008/09/23/effortless-offline-with-offlinerest/" target="_blank">post about the JsonRestStore and OfflineRest</a> back in 2008, he goes a little into detail there. Secondly, we need it for apps and tools that rely on persistence for other reasons, no matter if online or offline – like it happended to me. When I ran into Lawnchair, I had the idea to build a tool that was monitoring CSS selector usage on websites and apps (you know how you sometimes lose control about CSS selectors in webapps…). To achieve this, I needed to store data locally, and persistent.<br />
<span id="more-140"></span><br />
<strong>What dojo offers<br />
</strong></p>
<p>As I was using dojo&#8217;s excellent CSSRuleStore to find out what selectors where used, I wanted to switch from Lawnchair to a dojo solution. Dojo has dojox.storage (the above mentioned OfflineRest uses dojox.storage), which provides wrappers for the following backends: Gears, Flash, globalStorage and Adobe Air (globalStorage is Firefox&#8217;s early implementation of the early WhatWG storage draft). Hm. Not that much. Gears and Flash are 3rd party solutions, globalStorage is a Firefox-only-thingy (and old, though it&#8217;s still supported in current Versions) and Air is non-browser. That means: No IE without plugins. No Safari when Flash is not available.</p>
<p><strong>What dojo does not offer (but should)</strong></p>
<p>Guaranteed, reliable support for *any* browser. Without depending on 3rd party plugins. As of now, to have this, you&#8217;d need to use Lawnchair or <a href="http://github.com/lloyd/persist-js" target="_blank">persist,js</a>, which is pretty complete. Speaking of it, let me quote from it&#8217;s readme (it&#8217;s a good read on local persistent storage in general):</p>
<blockquote><p>The most notable attempt at addressing this problem [storing client-side persistent data] is probably Dojo Storage.  Unfortunately, Dojo Storage does not support Internet Explorer without Flash, and it does not support Safari or other WebKit-based<br />
browsers at all (at least, not without Flash).  Also, Dojo Storage is<br />
not standalone; it requires a several other Dojo components in order to<br />
operate.</p></blockquote>
<p>Whoa, even other JS tools mention the lack of support in dojo…</p>
<p><strong>New providers</strong></p>
<p>Attached to this post are wrappers for the following mechanisms:</p>
<ul>
<li>localStorage: this is the current spec, and it is supported by IE8, Firefox 3, Safari 4, Opera 10, Chrome 5.</li>
<li>userData behavior: this is Microsofts client-side storage for IE &lt; 8.</li>
<li>cookie: worst case fallback solution…</li>
</ul>
<p>With these three, there&#8217;s an almost 100% coverage of browser situations (see storage overview). There are still no-go scenarios, of course, such as IE7 with userData disabled and cookies disabled, but there&#8217;s no way to address them all.</p>
<p><strong>Notes on BehaviorStorageProvider</strong></p>
<p>This one uses the <a href="http://msdn.microsoft.com/en-us/library/ms531424%28VS.85%29.aspx" target="_blank">userData behavior</a>, present in IE from version 5 up. It works with DOM elements that have a special behavior assigned. You can then use  set/get/removeAttribute() methods to store data. It has some limitations though – of course…</p>
<ul>
<li>Maximum size varies from 64k to 1M – depending on the zone the site is in. So, you can&#8217;t rely on more than 64k.</li>
<li>UserData can be switched off in security settings.</li>
<li>I couldn&#8217;t find a way to read out stored keys if you don&#8217;t know them. Maybe this is some security thingy or just a bug – but it means that some methods in the provider don&#8217;t work. (that is, getNamespaces, getKeys and clear). To work around this, we have to take some of the precious storage space and store the keys and namespaces seperately.</li>
</ul>
<p><strong>Usage</strong></p>
<p>Copy the the providers into your <code>/dojox/storage</code> directory and add the needed <code>dojo.require</code>s to <code>/dojox/storage/_common.js</code>:</p>
<pre>dojo.require("dojox.storage.LocalStorageProvider");
dojo.require("dojox.storage.GearsStorageProvider");
dojo.require("dojox.storage.BehaviorStorageProvider");
//&gt;&gt;excludeStart("offlineProfileExclude", kwArgs.dojoxStorageBuildOption == "offline");
dojo.require("dojox.storage.WhatWGStorageProvider");
dojo.require("dojox.storage.FlashStorageProvider");
//&gt;&gt;excludeEnd("offlineProfileExclude");
dojo.require("dojox.storage.CookieStorageProvider");</pre>
<p><strong>What&#8217;s left?</strong></p>
<p>Well, it would be pretty cool to have a dojo.data API compliant store that uses dojox.storage as backend, so that you could write your apps using dojo.data calls and have a reliable offline backup. I started working on that, but then came Christmas, parents, vacation, new year and a lot of beer. But hey, it&#8217;s 2010 now, and there&#8217;s plenty of time left!</p>
<p><strong>Storage Overview</strong><br />
<!-- .overviewTable td {font-size: 10px; padding:2px 5px;} --></p>
<table class="overviewTable" border="0">
<tbody>
<tr>
<td>IE 6 / IE7</td>
<td>BehaviorStorageProvider<br />
FlashStorageProvider<br />
GearsStorageProvider<br />
CookieStorageProvider</td>
</tr>
<tr>
<td>IE 8</td>
<td>LocalStorageProvider<br />
GearsStorageProvider<br />
FlashStorageProvider<br />
CookieStorageProvider</td>
</tr>
<tr>
<td>Safari 3</td>
<td>FlashStorageProvider<br />
CookieStorageProvider</td>
</tr>
<tr>
<td>Safari 4</td>
<td>LocalStorageProvider<br />
FlashStorageProvider<br />
CookieStorageProvider</td>
</tr>
<tr>
<td>Chrome 5</td>
<td>LocalStorageProvider<br />
FlashStorageProvider<br />
CookieStorageProvider</td>
</tr>
<tr>
<td>Firefox 2</td>
<td>WhatWGStorageProvider (= globalStorage)<br />
GearsStorageProvider<br />
FlashStorageProvider<br />
CookieStorageProvider</td>
</tr>
<tr>
<td>Firefox 3</td>
<td>LocalStorageProvider<br />
GearsStorageProvider<br />
FlashStorageProvider<br />
CookieStorageProvider</td>
</tr>
<tr>
<td>Opera 10</td>
<td>LocalStorageProvider<br />
FlashStorageProvider (?)<br />
CookieStorageProvider</td>
</tr>
</tbody>
</table>
<p><strong>Files</strong></p>
<p><a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/dojox/storage/LocalStorageProvider.js" target="_blank">LocalStorageProvider.js</a><br />
<a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/dojox/storage/BehaviorStorageProvider.js" target="_blank">BehaviorStorageProvider.js</a><br />
<a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/dojox/storage/CookieStorageProvider.js" target="_blank">CookieStorageProvider.js</a><br />
<a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/dojox/storage/tests/test_storage.html" target="_blank">Storage Test Page</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2010/01/04/persistent-local-storage-with-dojo/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>More fun with strings: dojo.string.contains()</title>
		<link>http://jensarps.de/2009/11/29/more-fun-with-strings-dojo-string-contains/</link>
		<comments>http://jensarps.de/2009/11/29/more-fun-with-strings-dojo-string-contains/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 19:27:25 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Dojo Love]]></category>
		<category><![CDATA[Experiments in Web]]></category>
		<category><![CDATA[Goodies to go]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[string]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=114</guid>
		<description><![CDATA[In the series &#8220;convenience wrappers for small tasks that increase code readability&#8221;, today contains() is starring. Having a contains() method could also serve another purpose: to maybe prevent people from using match() to find out if a string contains a given substring (what is still proposed in some JS tutorials out there…). So, I want [...]]]></description>
			<content:encoded><![CDATA[<p>In the series &#8220;convenience wrappers for small tasks that increase code readability&#8221;, today contains() is starring. Having a contains() method could also serve another purpose: to maybe prevent people from using match() to find out if a string contains a given substring (what is still proposed in some JS tutorials out there…). So, I want the contains() method to also have a switch to work case-insensitive.</p>
<p>Besides indexOf(), there are some other ways to achieve this, so – let&#8217;s have a competition and find out who&#8217;s the fastest!<br />
<span id="more-114"></span></p>
<h3>The Contestants</h3>
<p><strong>replace and length</strong></p>
<p>One possibility is to replace the searched string with an empty string, read the length property of the modified string and compare it to the length of the haystack. If it&#8217;s different, the haystack contains the needle. Reading the length property is extra work, but comparing two integers is faster than comparing two strings, so maybe it&#8217;s faster in general.</p>
<p><strong>replace</strong></p>
<p>Again, replace the searched string with an empty string. Then compare the the modified string with the haystack. If they are different, the haystack contains the needle.</p>
<p><strong>split</strong></p>
<p>Take the haystack and try to split it using the needle as the seperator. If the result&#8217;s length is greater than one, the haystack contains the needle.</p>
<p><strong>indexOf</strong></p>
<p>Find the first occurance of needle in haystack; if the result is something else than -1, the haystack contains the needle.</p>
<h3>Results</h3>
<p>For testing, I did 10,000 iterations and retrieved the execution time in ms. The methods were tested in the order presented above.</p>
<p>On Chromium (Mac build, Version 4.0.203.0 here), replace + length is slightly faster than replace, and both are faster than split. indexOf is by far the fastest.</p>
<p>1) true: 7 / false: 3.5<br />
2) true: 7.5 / false: 3.5<br />
3) true: 10 / false: 8<br />
4) true: 2.5 / false: 3</p>
<p>Safari 4 has nearly the same results as Chromium, but the numbers tend to differ a lot from test to test.</p>
<p>1) true: 4-18, avg 10 / false: 2.5<br />
2) true: 4-19, avg 10 / false: 3<br />
3) true: 6-22. avg 13 / false: 6-23 avg. 16<br />
4) true: 2 / false: 3</p>
<p>On Firefox 3.5, split a bit faster than the two replace methods, but indexOf is again by far the fastest.</p>
<p>1) true: 13 / false 10<br />
2) true: 13 / false 10<br />
3) true: 10 / false 9<br />
4) true: 1.5 / false: 2</p>
<p>On IE 8 (run in a VM), both replace versions perform almost the same, and faster than split. Again, indexOf is fastest. Only 2 &#8211; 3 times faster than the replace methods, but still the fastest.</p>
<p>1) true: 35 / false: 25<br />
2) true: 30 / false: 25<br />
3) true: 60 / false: 50<br />
4) true: 15 / false: 15</p>
<p>You can run the tests yourself, if you are interested, the test page is <a href="http://jensarps.de/tests/dojo_tests/test_Contains.html" target="_blank">here</a>.</p>
<h3>Summary</h3>
<p>The results are pretty obvious: indexOf() outperforms the other contestants. Which is not really a surprise, considering that whatever Javascript does during indexOf() –  it has also to do the same before being able to do a split() or replace(). So, the proposed way for a contains() method is the following:</p>
<pre>dojo.string.contains = function(/* string */ needle, /* string */ haystack, /* bool */ caseInsensitive) {
    if(caseInsensitive) {
        needle = needle.toLowerCase();
        haystack = haystack.toLowerCase();
    }
    return haystack.indexOf(needle) !== -1;
}</pre>
<p>If you want to use contains() in your code, just copy the above lines somewhere in your code. Again, don&#8217;t forget to dojo.require(&#8220;dojo.string&#8221;) before.</p>
<p>Or, if you want to have beginsWith(), endsWith() and contains() all-in-one, use this: <a href="http://jensarps.de/tests/dojo_tests/dojo.string.addons.js" target="_blank">dojo.string.addons.js</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2009/11/29/more-fun-with-strings-dojo-string-contains/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>dojo.string.beginsWith()</title>
		<link>http://jensarps.de/2009/10/27/dojo-string-beginswith/</link>
		<comments>http://jensarps.de/2009/10/27/dojo-string-beginswith/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 20:36:18 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Dojo Love]]></category>
		<category><![CDATA[Goodies to go]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[string]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=78</guid>
		<description><![CDATA[Most cases where you find String.substr() in the wild are to check if a given string begins with a certain other string. Be it checking for a prefix or sorting out zipcodes that begin with certain numbers. And because code readability is a good thing (really, it is important), it would be nice to have [...]]]></description>
			<content:encoded><![CDATA[<p>Most cases where you find String.substr() in the wild are to check if a given string begins with a certain other string. Be it checking for a prefix or sorting out zipcodes that begin with certain numbers. And because code readability is a good thing (really, it <em>is</em> important), it would be nice to have a String.beginsWith() method. Or, because of dojo love, a dojo.string.beginsWith() method.</p>
<p>Consider the following code:</p>
<pre>var nearbyZipcodes = dojo.filter(givenZipcodes,function(zipcode){
    return dojo.string.beginsWith(zipcode,'12');
});</pre>
<p><span id="more-78"></span><br />
No need to tell you what this does, right? So, let&#8217;s do this then! The only thing left is to think about performance: Is there a difference between String.substr() and String.substring()? And can we get faster than the two?</p>
<p>If we have very short needles to look for in our haystack, one could consider the following approach:</p>
<pre>dojo.string.beginsWith = function(/* string */ needle, /* string */ haystack) {
    var i,
        len = needle.length;
    if(needle.length &gt; haystack.length) {
        return false;
    }
    for(i = 0; i &lt; len; i++) {
        if(needle.charAt(i) !== haystack.charAt(i)) {
            return false;
        }
    }
    return true;
}</pre>
<p>For very short needles, or when we expect close to no hits, this might be faster. So I set up a test page and let the different methods run against each other. The results clearly spoke against the char iteration method: On Firefox, iteration was <em>always</em> slower, even when the iteration method could return false after the first character. And when it had to iterate more often, times went up (I somehow had in mind Tracemonkey was perfect for simple iterations – but in this case it won&#8217;t help). Only on Safari the iteration method could compete with native substr() / substring() – but was never significantly faster. So, we&#8217;ll stick to the native methods (there was no real difference between the two).</p>
<p>More convenience?</p>
<p>Depending on your datasource, you might want to trim the input. No problem, as we use dojo, we can use it&#8217;s super fast trim and end up with the following:</p>
<pre>dojo.string.beginsWith = function(/* string */ needle, /* string */ haystack, /* bool */ trimBefore) {
    if(trimBefore) {
        needle = dojo.string.trim(needle)
    }
    if(needle.length &gt; haystack.length) {
        return false;
    }
    return haystack.substr(0,needle.length) === needle;
}</pre>
<p>So simple, so sweet.</p>
<p>You can run the tests for yourself, the page is located here: <a href="http://jensarps.de/tests/dojo_tests/test_beginsWith.html" target="_blank">test_beginsWith.html</a></p>
<p>If you want to use beginsWith in your code, just put the lines above it anywhere in your code – but don&#8217;t forget to dojo.require(&#8216;dojo.string&#8217;) before.</p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2009/10/27/dojo-string-beginswith/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>A collapsible fieldset as dojo widget</title>
		<link>http://jensarps.de/2009/10/16/a-collapsible-fieldset-as-dojo-widget/</link>
		<comments>http://jensarps.de/2009/10/16/a-collapsible-fieldset-as-dojo-widget/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 18:43:01 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Dojo Love]]></category>
		<category><![CDATA[Goodies to go]]></category>
		<category><![CDATA[dijit]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[widget]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=59</guid>
		<description><![CDATA[Though many people would disagree, I for one like to use fieldsets to structure complex forms. Even better do I like fieldsets that are collapsible. As there is no such fieldset with dojo, I decided to write my own widget. While doing so, I learnt an interesting lesson… First, I wrote it pretty simple, inheriting [...]]]></description>
			<content:encoded><![CDATA[<p>Though many people would disagree, I for one like to use fieldsets to structure complex forms. Even better do I like fieldsets that are collapsible.</p>
<p>As there is no such fieldset with dojo, I decided to write my own widget. While doing so, I learnt an interesting lesson…</p>
<p>First, I wrote it pretty simple, inheriting the widget from dijit._Widget and dijit._Templated. It had a toggle button next to its legend, which could be clicked. The toggle was a simple display none/block change.<br />
<span id="more-59"></span><br />
But I wanted it to be accessible via the keyboard – so I added a tabIndex and a key handler. Next, I wanted it to be able to hold and parse widgets, so I inherited it from dijit.layout.ContentPane so I could make use of the content setter. Then I wanted it to animate smoothly, so I added animations, and so on… You get the point, I guess. Well, this went on for a while, until I made an unpleasant discovery: My fieldset was almost a clone of dijit.TitlePane. Ugh.</p>
<p><em>I had put all the time into creating a copy of something, that already existed.</em></p>
<p>So I inherited the fieldset widget from dijit.TitlePane and ended up with less than 50 lines of code. And it was a matter of minutes to do so. Ok, lesson learned: If you need something that doesn&#8217;t exist and you are going to code it – first check if there&#8217;s something that behaves similar to what you want. Or similar to what you <em>might want in the future</em>. If I had invested a little more time in thinking about the fieldset widget before starting to code, it would have been obvious that I wanted the above mentioned features one day. And I would have saved a lot of time.</p>
<p>Well, however, here it is: a collapsible fieldset, coming with all the ContentPane goodness (child widgets, remote loading,…).</p>
<p>You can create it via markup (I put it into a namespace called &#8220;app&#8221;; choose a namespace you like):</p>
<pre>&lt;fieldset dojotype="app.Fieldset"&gt;
    &lt;legend&gt;Legend&lt;/legend&gt;
    Content
&lt;/fieldset&gt;</pre>
<p>or programmatically:</p>
<pre>var fieldset = new app.Fieldset({legend:'dojo fieldset', id: 'someId'},dojo.create('div',{},dojo.body()));</pre>
<p>The fieldset takes pretty much the same arguments as dijit.TitlePane. To change the legend, use <code>dojo.attr('legend','Teh new legend')</code>, to change the content <code>dojo.attr('content',content)</code> as usual. To stay close to TitlePane, I left <code>_setTitleAttr()</code> in it, but it is an alias for <code>_setLegendAttr()</code>.</p>
<p>The code is simple (after I inherited from TitlePane), I only added a method to setup the legend tag and changed the methods that handle hover states, as the TitlePane&#8217;s methods paid no respect to the dijit&#8217;s base class. The fieldset is closed by default, but you can add <code>open="true"</code> to the markup (or add <code>open: true</code> to the constructor args) to make it start open. You can style it as you would style any other widget.</p>
<p>The testpage is over here: <a href="http://jensarps.de/tests/dojo_tests/test_Fieldset.html" target="_blank">test_Fieldset.html<br />
</a> Code: <a href="http://jensarps.de/tests/dojo_tests/dojo-1.3.2/app/Fieldset.js" target="_blank">Fieldset.js</a><br />
Template: <a href="http://jensarps.de/tests/dojo_tests/dojo-1.3.2/app/templates/Fieldset.html" target="_blank">Fieldset.html</a></p>
<p><strong>Update</strong>: If you have downloaded the code and intend to use it, please re-download it, as I updated a method and fixed a namespace confusion (and added doc).</p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2009/10/16/a-collapsible-fieldset-as-dojo-widget/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>dojox.analytics.Urchin for jQuery</title>
		<link>http://jensarps.de/2009/10/03/dojox-analytics-urchin-for-jquery/</link>
		<comments>http://jensarps.de/2009/10/03/dojox-analytics-urchin-for-jquery/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 17:28:41 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Framework Peace]]></category>
		<category><![CDATA[Goodies to go]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[tracking]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=38</guid>
		<description><![CDATA[Or: Still ending the ga.js wait… It has become quiet here the last weeks – due to an awesome trip to Italy. Returning home, I decided to put Google Analytics on this page. As I always hate waiting for the ga.js to load while visiting websites, I wanted a mechanism to delay the load of [...]]]></description>
			<content:encoded><![CDATA[<p>Or: <em>Still</em> ending the ga.js wait…</p>
<p>It has become quiet here the last weeks – due to an awesome trip to Italy. Returning home, I decided to put Google Analytics on this page.</p>
<p>As I always hate waiting for the ga.js to load while visiting websites, I wanted a mechanism to delay the load of it. Why this is a good idea has been discussed often enough elsewhere, so we take it as fact. Peter Higgins once <a href="http://higginsforpresident.net/2008/06/google-analytics-after-onload/" target="_blank">wrote such a wrapper for dojo</a>, and as of dojo 1.3, it&#8217;s officially included in dojox (see <a href="http://alex.dojotoolkit.org/2009/04/ending-the-gajs-wait/" target="_blank">Alex Russel&#8217;s post</a>). But this WordPress theme runs jQuery, and I didn&#8217;t want to have two frameworks in one website – so I searched for something that did the job for jQuery.<br />
<span id="more-38"></span><br />
But I didn&#8217;t really find what I was looking for. Well, there <em>are</em> some jQuery plugins that provide functionality like I wanted. Some were overpowered, some poorly written – and in the end, they all relied on jQuery.getScript(). The problem is, that getScript() adds a random parameter to the GET call, so that the called script is never cached. While this <em>may</em> be useful for some situations, in this case it&#8217;s really annoying and undesireable. In addition, I liked the idea of dojox.analytics.Urchin to not really <em>wait</em> for the script to be loaded, but instead to go see every now and then if the _gat global variable is present, and to give up after some time in case something went wrong.</p>
<p>So I decided to &#8220;port&#8221; dojox.analytics.Urchin to jQuery. It works almost the same as it&#8217;s dojo origin, with two major differences: First, you can&#8217;t have several instances of it running, you call it directly via jQuery.urchin.load(args). Second, there&#8217;s an option waitForDOM, set to true as default, that delays the loading of ga.js until the DOM is ready. If you call jQuery.urchin.load() from within a jQuery(document).ready() block, set this to false.</p>
<p>Example? Here you go:</p>
<pre>&lt;script type="text/javascript" src="jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery.urchin.js"&gt;&lt;/script&gt;

&lt;script type="text/javascript"&gt;
jQuery.urchin.load({acct:'UA-111111-1'});
&lt;/script&gt;</pre>
<p>Or, if you need more options:</p>
<pre>&lt;script type="text/javascript"&gt;
$(document).ready(function() {
    // do some stuff
    // ...
    // load ga.js
    $.urchin.load({
        acct:'2234-2342',
        timeout: 8000,
        waitForDOM: false
    });
});
&lt;/script&gt;</pre>
<p>You can get the file here: <a href="http://jensarps.de/tests/jquery_analytics/jquery.urchin.js" target="_blank">jquery.urchin.js</a></p>
<p>Uncompressed version: <a href="http://jensarps.de/tests/jquery_analytics/jquery.urchin.uncompressed.js">jquery.urchin.uncompressed.js</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2009/10/03/dojox-analytics-urchin-for-jquery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Static data handling in PHP</title>
		<link>http://jensarps.de/2009/09/03/static-data-handling-in-php/</link>
		<comments>http://jensarps.de/2009/09/03/static-data-handling-in-php/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 19:13:42 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Goodies to go]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=26</guid>
		<description><![CDATA[Every now and then I stumble upon PHP Code dealing with config files. Besides being happy that people use config files (uh, yes, it happens too often that people don&#8217;t…), I am often unhappy with how they&#8217;re dealing with config files. You can find the ugliest things out there, like arrays in .php files (my [...]]]></description>
			<content:encoded><![CDATA[<figure><img class="alignleft size-thumbnail wp-image-32" title="Bild 17" src="http://jensarps.de/wp-content/uploads/2009/09/Bild-17.png" alt="Bild 17" width="150" />Every now and then I stumble upon PHP Code dealing with config files. Besides being happy that people use config files (uh, yes, it happens too often that people don&#8217;t…), I am often unhappy with how they&#8217;re dealing with config files. You can find the ugliest things out there, like arrays in .php files (my favorite). However, even if config files are used, there are strange things happening to them, like being read once and serialized into a constant.</p>
<p>So I want to share today a very primitive static data handler that I use for quite some time now, and wich has always served me well. By static, I mean data that doesn&#8217;t change during runtime, like smtp server connection data, database connection data and the likes.</p>
<p><span id="more-26"></span></figure>
<p>The idea is to have a seperate directory (named &#8220;static&#8221; in my case) with .data files in it. Every .data file should care about a certain aspect of static data needed in an application. This directory is then blocked via an .htaccess file, containing the single line:</p>
<pre># file: .htaccess
Deny From All</pre>
<p>During the bootsrap process of your app, the collector is called to walk through that directory and gather the data from all the files:</p>
<pre>// file: bootstrap.php
// load static data
YourProject_StaticData::getInstance()-&gt;collectStaticData();</pre>
<p>These files are pretty much standard config files, so they are readable via php&#8217;s function parse_ini_file. That function has two major limitations: It cannot handle hierarchy beyond two levels and it breaks when it encounters a quote character in a value. These limitations are discussed elsewhere, but with this static data collector we can at least push the first one a level further away. A data file could look like this:</p>
<pre># file: mailconfig.data
[smtp]
host     = somehost.tld
auth     = true
username = user@somehost.tld
password = somepass
[lists]
whitelist = "goodone@example.com,admin@somehost.tld"
blacklist = "badone@example.com"
[options]
checkwhitelist = false
checkblacklist = true
# ...</pre>
<p>To get the connection data to the applications&#8217;s smtp account, you&#8217;d simply call:</p>
<pre>$smtpConfig = YourProject_StaticData::getInstance()-&gt;getSubSection('mailconfig','smtp');</pre>
<p>Fairly easy to use, pretty and readable. And it also is very handy for something that *very* often annoys me when looking into some client&#8217;s code: establishing a connection to a database. To different databases in most cases, for development, testing and deployment. I&#8217;ve seen pretty awkward attempts to handle this – but it can be done with one line of code, regardless of where the code is running. Say, you use <a href="http://www.doctrine-project.org/" target="_blank">Doctrine</a> as ORM for your database, and have a data file like the following, using host names as keys (besides all my love for the <a href="http://en.wikipedia.org/wiki/Nosql" target="_blank">NoSQL</a> movement, I run into a mysql database on nearly every project):</p>
<pre># file: dbms.data
project.local    = "mysql://user:pass@localhost/project_db"
test.project.tld = "mysql://testuser:testpass@project.tld/test_project_db"
project.tld      = "mysql://user:pass@project.tld/project_db"</pre>
<p>you can easily connect to your database by defining a constant that contains the current host name (wich is a good idea, in general) and call</p>
<pre>// file: bootstrap.php
//set up a connection
Doctrine_Manager::connection(
    YourProject_StaticData::getInstance()-&gt;getSubSection('dbms',HOST),
    'mainConnection'
)-&gt;setCharset("utf8");</pre>
<p>Clean and short. And independant from your location – just see to it that your data file contains the right connection data for each host, and never touch that line of code in your bootstrapping process again.</p>
<p>The PHP class uses the <a href="http://en.wikipedia.org/wiki/Singleton_pattern" target="_blank">singleton design pattern</a> (as you already know from the code above), and is less than 100 lines of code in size. Including doc. It&#8217;s as simple as it is handy. And it can be easily extended – if the need arises, what never happened to me.</p>
<p>I hope you can find it as useful as I do!</p>
<p>You can grab the file over here: <a href="/code/StaticData.php.txt">StaticData.php</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2009/09/03/static-data-handling-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

