<?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; js</title>
	<atom:link href="http://jensarps.de/tag/js/feed/" rel="self" type="application/rss+xml" />
	<link>http://jensarps.de</link>
	<description></description>
	<lastBuildDate>Tue, 07 Sep 2010 14:11:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>localStorage Performance Test Results</title>
		<link>http://jensarps.de/2010/09/07/localstorage-performance-test-results/</link>
		<comments>http://jensarps.de/2010/09/07/localstorage-performance-test-results/#comments</comments>
		<pubDate>Tue, 07 Sep 2010 11:17:50 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Experiments in Web]]></category>
		<category><![CDATA[Storage]]></category>
		<category><![CDATA[client-side storage]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[localStorage]]></category>
		<category><![CDATA[persistence]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=260</guid>
		<description><![CDATA[It&#8217;s been some time since I last updated this blog, mostly because there&#8217;s plenty going on these days. However, there&#8217;s something I&#8217;ve been wanting to publish for quite some time now: The results of the localStorage performance tests I ran several weeks ago. As I am currently working on performance tests for Mozilla&#8217;s IndexedDB implementation, ]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been some time since I last updated this blog, mostly because there&#8217;s plenty going on these days. However, there&#8217;s something I&#8217;ve been wanting to publish for quite some time now: The results of the localStorage performance tests I ran several weeks ago. As I am currently working on performance tests for Mozilla&#8217;s IndexedDB implementation, which is available in latest Minefield releases, I got reminded that there are still other results to publish – so, here we go:</p>
<p><span id="more-260"></span></p>
<p>Among other tests, the main thing I wanted to know is how long does it take to read or write 1000 entries from/to localStorage. The keys were of the form &#8220;key000&#8243;, the values &#8220;val000&#8243;, with increasing numbers. So the tests were using minimal data – only 6  bytes – but the results are still useful to get an idea of how it goes – and how the browsers perform compared to each other.</p>
<p><strong>Desktop</strong></p>
<p>All test were run on a Mac Mini. Opera and IE were tested on a virtual machine, so there might be an additional performance penalty based on virtualization. However, here are the numbers (average time needed to run the respective method 1000 times):</p>
<p>Safari 4:<br />
- getItem: 1.4ms<br />
- setItem: 1.7ms<br />
- key: 0.8ms</p>
<p>Chrome:<br />
- getItem: 240ms<br />
- setIem: 280ms<br />
- key: 230ms</p>
<p>Firefox:<br />
- getItem: 77ms<br />
- setItem: 2100ms<br />
- key: 25ms</p>
<p>Opera:<br />
- getItem: 19ms<br />
- setItem: 20ms<br />
- key: 18ms</p>
<p>IE8:<br />
- getItem: 5ms<br />
- setItem: 72ms<br />
- key: 3.6ms</p>
<p><strong>Mobile</strong></p>
<p>As we can see, Safari is lightening fast. That made me want to run the tests on a mobile phone that has a modern Safari browser. I took an HTC Desire, wich comes with Android 2.1, and thus has a Safari capable of localStorage. Here are the results:</p>
<p>HTC Desire:<br />
- getItem: 16.4ms<br />
- setItem: 19.5ms<br />
- key: 8.7ms</p>
<p>This is pretty amazing, considering that it is a phone. It still beats most of the browseres on the desktop.</p>
<p>If I find that test page again (uh, yeah, it&#8217;s lost somehow), I&#8217;ll run the tests again with newer browser releases and publish the link here, so you can run the tests yourself.</p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2010/09/07/localstorage-performance-test-results/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>Promises with dojo &#8211; a lightweight alternative to dojo.Deferred</title>
		<link>http://jensarps.de/2010/02/03/promises-with-dojo-a-lightweight-alternative-to-dojo-deferred/</link>
		<comments>http://jensarps.de/2010/02/03/promises-with-dojo-a-lightweight-alternative-to-dojo-deferred/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 23:27:16 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Dojo Love]]></category>
		<category><![CDATA[Experiments in Web]]></category>
		<category><![CDATA[CommonJS]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[dojox]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[js]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=190</guid>
		<description><![CDATA[Update: Micheil Smith had a cool idea to improve this and posted it in the comments. I have updated the test page and the code examples to reflect his idea. Thanks Micheil!
Update II: Ben Hockey proposed to do the whole thing without using the pub/sub system. I for one think its a good idea, but ]]></description>
			<content:encoded><![CDATA[<p><em><strong>Update:</strong> <a href="http://twitter.com/Miksago" target="_blank">Micheil Smith</a> had a cool idea to improve this and posted it in the comments. I have updated the test page and the code examples to reflect his idea. Thanks Micheil!</em></p>
<p><em><strong>Update II:</strong> <a rel="nofollow" href="#comment-489">Ben Hockey</a> proposed to do the whole thing without using the pub/sub system. I for one think its a good idea, but in case you want the topic version, I&#8217;ll leave the test page and add <a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/test_Promise_notopic.html" target="_blank">another one</a> with the topic-less version. Thanks Ben!</em></p>
<p><em><strong>Update III</strong>: Dojo 1.5 introduces robust Promises with dojo.deferred as Krys Zyp explains in <a href="http://www.sitepen.com/blog/2010/05/03/robust-promises-with-dojo-deferred-1-5/" target="_blank">this SitePen post</a>.<br />
</em></p>
<p>&#8212;</p>
<p>One of the things/ideas/concepts that I really like about CommonJS is Promises.</p>
<p>Promises? A brief explanation from the <a href="http://wiki.commonjs.org/wiki/Promises" target="_blank">CommonJS API</a>:</p>
<blockquote><p>Promises provide a well-defined interface for interacting with an object  that represents the result of an action that is performed  asynchronously, and may or may not be finished at any given point in  time.</p></blockquote>
<p>To hear more about Promises, I highly recommend <a href="http://www.michaelharrison.ws/weblog/?p=198" target="_blank">these</a> <a href="http://www.sitepen.com/blog/2010/01/19/commonjsjsgi-the-emerging-javascript-application-server-platform/" target="_blank">two</a> posts.<br />
<span id="more-190"></span><br />
That concept is not entirely new. The dojo toolkit has <a href="http://docs.dojocampus.org/dojo/Deferred" target="_blank">dojo.Deferred</a>, which does a similar job. You create a Deferred, add (multiple) callbacks and error handlers to it, and when it fires off, all your handlers get called. But dojo.Deferred is pretty heavyweight. It&#8217;s loads of code. And it works with <code>.addCallback()</code> and <code>.addErrback()</code> methods – not with <code>.then()</code> methods, which provide maximum readability.</p>
<p><strong>The goal</strong></p>
<p>What I want to have is the follwing code running (with dojo):</p>
<pre>asyncComputeTheAnswerToEverything().
    then(addTwo).
    then(printResult, onError);</pre>
<p><em>(This is the example code from the proposed CommonJS Promise API)</em></p>
<p>And I want the execution to continue right after <code>doSomethingAsnyc()</code> – the async call should still be non-blocking. The <code>.then()</code> methods should recieve the results of the previous part of the chain, but still be non-blocking. Luckily, dojo provides a tool that allows us to achieve this: the publish/subscribe system.</p>
<p><strong>Let&#8217;s do it</strong></p>
<p>When we have unique topics for each promise made, we can subscribe the <code>.then()</code> method to the current topic in the chain, and publish the next topic when the data handlers are done computing. Within the <code>then()</code> method we need to check if the data we recieve is an error or not, to determine wich handler we need to call. The spec also demands a progress handler – if we wanted to implement that, we needed to add another topic, but I left that out.</p>
<p>We only need to kick off  the whole thing when we create the first promise, then the rest takes care for itself. Including the changes proposed by Micheil, what you have to do is pretty trivial and you don&#8217;t have to care about unique topics or the pub/sub system at all. The <code>asyncComputeTheAnswerToEverything()</code> function mentioned above would look like the following:</p>
<pre>var asyncComputeTheAnswerToEverything = function(){
	var promise = new dojox.Promise();
	window.setTimeout(function(){ // some async operation
		var data = 42;
		promise.emit(data);
	},2000);
	return promise;
};</pre>
<p>You create a Promise and store a reference to it. You return the promise and use the reference to it to kick off the chain when the data is there. Everything else runs on it&#8217;s own now.<br />
Go to the <a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/test_Promise_notopic.html" target="_blank">test page</a> or theand check the source &#8211; it contains the Promise code and the example functions. Open the console and run <code>testSpec();</code> to start off the example code from the CommonJS API proposal.</p>
<p><strong>Usage</strong></p>
<p>As a namespace to put the Promise into I chose dojox – but choose whatever floats your boat. You can just drop the promise code somewhere into your code, or, if want to <code>dojo.require("dojox.Promise")</code> it, create a file named <code>Promise.js</code> that contains the code and place a <code>dojo.provide("dojox.Promise");</code> as the first line in it. Save the file in the dojox directory and you&#8217;re done. (Well, to be honest, this violates the dojox naming convention, but if its just in your project, it&#8217;s ok and it will work.)</p>
<p>Any questions left? Feel free to leave a comment, @ me at twitter or drop me a line.</p>
<p><strong>References / Files / More<br />
</strong></p>
<ul>
<li><a href="http://wiki.commonjs.org/wiki/Promises" target="_blank">CommonJS Promise API Proposal</a></li>
<li><a href="http://www.sitepen.com/blog/2010/01/19/commonjsjsgi-the-emerging-javascript-application-server-platform/" target="_blank">Post by Kris Zyp @ SitePen blog about CommonJS</a></li>
<li><a href="http://www.michaelharrison.ws/weblog/?p=198" target="_blank">Post on www.michaelharrison.ws about promises and more</a></li>
<li><a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/test_Promise.html" target="_blank">the test page (using topics and pub/sub)</a></li>
<li><a href="http://jensarps.de/tests/dojo_tests/dojo-release-1.4.0-src/test_Promise_notopic.html">the test page (w/o topics, recommended)</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2010/02/03/promises-with-dojo-a-lightweight-alternative-to-dojo-deferred/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Working with the Curve &#8211; Advanced Animation with Dojo</title>
		<link>http://jensarps.de/2010/01/22/working-with-the-curve-advanced-animation-with-dojo/</link>
		<comments>http://jensarps.de/2010/01/22/working-with-the-curve-advanced-animation-with-dojo/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 21:03:16 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Dojo Love]]></category>
		<category><![CDATA[Experiments in Web]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[dojox]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[js]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=170</guid>
		<description><![CDATA[If you use animations, you probably use them to animate CSS properties. But this post is about some real bareknuckle animation – using the dojo toolkit. We&#8217;ll have a look into dojo.Animation and talk about the curve, the line, easing and rate, and we&#8217;ll check out (the somehow undocumented) dojox.fx._core – and see how to ]]></description>
			<content:encoded><![CDATA[<p>If you use animations, you probably use them to animate CSS properties. But this post is about some <em>real bareknuckle animation</em> – using the dojo toolkit. We&#8217;ll have a look into dojo.Animation and talk about the curve, the line, easing and rate, and we&#8217;ll check out (the somehow undocumented) dojox.fx._core – and see how to work with multidimensional lines.</p>
<p><span id="more-170"></span></p>
<p><strong>The Curve</strong></p>
<p>Every dojo.Animation needs a curve. If you call <code>animateProperty</code> or it&#8217;s shorthand <code>anim</code>, you don&#8217;t have to provide the curve for yourself, dojo will do it for you – if you build an animation using <code>new dojo.Animation()</code>, you have to provide your own curve. You can think of the curve as of a line that the animation walks on. The line is already present before the animation starts to walk it, and it can always take a break and pause in the middle and eventually continue walking where it had stopped. To create a curve, you need to call <code>new dojo._Line(start, end)</code>. In return, you get an object with three properties: <code>end</code>, <code>start</code> and a <code>getValue()</code> method.</p>
<pre>var anim = new dojo.Animation({
	curve: new dojo._Line(0,100)
});</pre>
<p><strong>Easing</strong></p>
<p>The curve will then be modified by a easing function. By default, this is the linear <code>dojo._defaultEasing</code>. Easing breathes a bit of life into the curve, you can say. Other properties of dojo.Animation that affect the curve are <code>rate</code> and <code>duration</code>. <code>rate</code> is the timespan between two frames. To calculate the targeted fps, use <code>(1000/rate)</code>. By default, dojo aims at 50 fps.</p>
<pre>var anim = new dojo.Animation({
	curve: new dojo._Line(0,100),
	easing: dojo.fx.easing.quadInOut
});</pre>
<p><strong>Waking Life</strong></p>
<p>To get some numbers out of <code>dojo.Animation</code>, let&#8217;s let it go wild and <code>play()</code>. When using <code>animateProperty</code> or the likes, you just fire and forget. In our case, we need to get the numbers. To achieve this, we connect to our animation&#8217;s <code>onAnimate</code> event. This is fired on every frame of the animation. When your connected function is called, you get – who would have guessed – the current value of the curve. Now you have a function called at a given rate, for a given period of time and you get get a numeric value that is already calculated for you. Decent!</p>
<pre>dojo.connect(anim,'onAnimate',function(curveValue){
	// do something
});</pre>
<p>To see some curves in action, go to <a href="http://jensarps.de/tests/dojo_tests/animation.html" target="_blank">this test page</a>, open the console and type <code>play(1);</code> and <code>play(2);</code> and check the source code to see what&#8217;s happening.</p>
<p><strong>Multidimensional Curves</strong></p>
<p><code>dojo._Line</code> generates only one-dimensional curves. But, there is <code>dojox.fx._core</code>, which contains an (old) version of <code>dojox.fx._Line</code>, which is capable of creating multi-dimensional curves. To use it, you have to explicitely <code>dojo.require("dojox.fx._core")</code>. It&#8217;s a bit odd, but the _core file contains only the _Line, and it is not loaded when requiring &#8220;dojox.fx&#8221;. Well, whatever, you can pass arrays of numbers into <code>dojox.fx._Line</code>:</p>
<pre>new dojox.fx._Line([0,2],[100,6]);</pre>
<p>Now you have a multi-dimensional curve. Or, if you could say, you have two curves in one. You can (technically) pass an unlimited amount of numbers into <code>dojox.fx._Line</code>. When you hand this curve to a <code>dojo.Animation</code>, it will animate all dimensions of the curve. And it will modify all dimensions of the curve according to easing, rate and duration. If you connect a function to <code>onAnimate</code>, it will now recieve an array of numbers.</p>
<pre>var anim = new dojo.Animation({
	curve: new dojox.fx._Line([0,2],[100,6]),
	easing: dojo.fx.easing.quadInOut
});</pre>
<p>Head over to the <a href="http://jensarps.de/tests/dojo_tests/animation.html">test page</a> again, and type <code>play(3);</code> into the console. Now, the width of the bars is also animated – by the same animation function that calculates the height of the bars.</p>
<p><strong>What now?</strong></p>
<p>If your mind is still not blown away with ideas about how to use this, let me give you a start:</p>
<ul>
<li>animate position, width and height of a browser window and use it as a screensaver for some unknowing, yet thankful visitor…</li>
<li>take some CSS 2D and 3D transisitions/transforms and animate away…</li>
<li>canvas! No need to say another word…</li>
<li>Still too banal? Go WebGL! Grab some 3DContext and animate an evil ball of jelly jumping around!</li>
</ul>
<p>In short: dojo&#8217;s animation system allows you to not only animate CSS properties, but gives you a good tool for  animations in general. You get the curves on the one hand, but you also get the &#8220;player&#8221; for these curves, including play/pause/stop/gotoPercent methods. And dojo.fx.easing has a lot of easing functions in stock.</p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2010/01/22/working-with-the-curve-advanced-animation-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&#8217;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 has been ]]></description>
			<content:encoded><![CDATA[<p>Last year, <a href="http://twitter.com/brianleroux" target="_blank">Brian Leroux</a>&#8217;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>7</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(&#8221;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(&#8217;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 the widget ]]></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>5</slash:comments>
		</item>
		<item>
		<title>Safari and window.open – How to do it</title>
		<link>http://jensarps.de/2009/10/08/safari-and-window-open-%e2%80%93-how-to-do-it/</link>
		<comments>http://jensarps.de/2009/10/08/safari-and-window-open-%e2%80%93-how-to-do-it/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 10:22:07 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Browser Struggle]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[safari]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=50</guid>
		<description><![CDATA[There is still some traffic coming in from people who are searching for how to deal with the safari popup blocker. So I thought it might be nice to also tell what you can do about it – as most people want solutions, not backgrounds…
So, here you go:
It&#8217;s pretty simple, really. What to do? Well, ]]></description>
			<content:encoded><![CDATA[<p>There is still some traffic coming in from people who are searching for how to deal with the <a href="http://jensarps.de/2009/08/21/safari-and-window-open/">safari popup blocker</a>. So I thought it might be nice to also tell what you can do about it – as most people want solutions, not backgrounds…</p>
<p>So, here you go:</p>
<p>It&#8217;s pretty simple, really. What to do? Well, call window.open() while the popup blocker still allows it, and store a reference to the window object. Then, later, do with it what you want. That is, changing the location in most cases.<br />
<span id="more-50"></span><br />
Huh, that&#8217;s all? No magic? Nope, sorry. The popup blocker&#8217;s rules cannot be bent.</p>
<p>Say, you have a connection like this (I stay with the example code of the prior post):</p>
<pre>dojo.connect(dojo.byId('b9'),'onclick',function(evt){
    dojo.publish('/opener/callOpen');
});</pre>
<p>Then call window.open in your subscription:</p>
<pre>dojo.subscribe('/opener/callOpen',function() {
    var winRef = window.open();
    dojo.xhrGet({
        url: window.location.href,
        load: dojo.hitch(opener,function(){
            this.open(winRef);
        })
    });
});</pre>
<p>And let your open() know there might be a window object coming in:</p>
<pre>opener = {
    open: function(windowReference) {
        var newWin = windowReference || window.open();
        // see if we get a window object
        console.log(newWin);
    }
};</pre>
<p>In case your new window will be open and visible for some time until you can work with it, don&#8217;t forget to let the user know that the window will get some content in a few, e.g. point the new window&#8217;s url to some nice &#8220;please wait&#8221; page.</p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2009/10/08/safari-and-window-open-%e2%80%93-how-to-do-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>3D Canvas Walker revisited</title>
		<link>http://jensarps.de/2009/08/27/3d-canvas-walker-revisited/</link>
		<comments>http://jensarps.de/2009/08/27/3d-canvas-walker-revisited/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 20:01:26 +0000</pubDate>
		<dc:creator>Jens Arps</dc:creator>
				<category><![CDATA[Experiments in Web]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[js]]></category>

		<guid isPermaLink="false">http://jensarps.de/?p=12</guid>
		<description><![CDATA[One of the things that fascinated me most about computers since I was a teen, was their ability to simulate a three-dimensional space where one could move around in.
That&#8217;s why I was so intrigued when I read Jacob Seidelin&#8217;s post about “Creating pseudo 3D Games“. I had to play around with it, as I wanted ]]></description>
			<content:encoded><![CDATA[<div id="attachment_22" class="wp-caption alignleft" style="width: 160px"><a href="http://jensarps.de/wp-content/uploads/2009/08/walker-screenshot.jpg"><img class="size-thumbnail wp-image-22 " title="walker-screenshot" src="http://jensarps.de/wp-content/uploads/2009/08/walker-screenshot.jpg" alt="Screenshot" width="150" /></a><p class="wp-caption-text">Screenshot</p></div>
<p>One of the things that fascinated me most about computers since I was a teen, was their ability to simulate a three-dimensional space where one could move around in.</p>
<p>That&#8217;s why I was so intrigued when I read Jacob Seidelin&#8217;s post about “<a href="http://dev.opera.com/articles/view/creating-pseudo-3d-games-with-html-5-can-1/">Creating pseudo 3D Games</a>“. I had to play around with it, as I wanted to have mouse control in it, but performance was so bad that it was impossible. So I laid aside that idea. Eventually, he <a href="http://dev.opera.com/articles/view/3d-games-with-canvas-and-raycasting-part/">continued this project</a> and used it for something pretty awesome called “<a href="http://blog.nihilogic.dk/2008/07/wolfenflickr-3d-unlikely-mashup.html">WolfenFlickr</a>&#8220;, where you can walk around and look at Flickr photos, attached to walls. As I said, pretty awesome.</p>
<p>Anyway, what I wanted was mouse navigation and strafe keys, as you have it in shooters – this kind of moving around always gives me the feeling of being “free“ in a way. Experiencing that freedom in a web page (w/o flash, of course) was still on my mind.</p>
<p><span id="more-12"></span></p>
<p>And the I stumbled upon Ben Joffe&#8217;s <a href="http://www.benjoffe.com/code/demos/canvascape/textures">textured Canvascape 3D-Walker</a>. The performance of the canvas element drawing the image slices was better than letting the browser render single elements for each slice – much better. In fact, the idea of mouse control immeadiately popped up again and I had to give it a try. And – it worked! Of course it has some drawbacks (that is, when the cursor leaves the browser window, there&#8217;s no more control…), but it gave me that feeling of freedom while moving around!</p>
<p>Fooling around with the canvas element was fun and tought me about it&#8217;s image methods. And I hope to find more time to take it further…</p>
<p>Of course there&#8217;s an aweful lot of work ahead if one would want this to be pretty (it&#8217;s all bricks now, no interaction, perspective issues, no smooth movement on strafe, and so on…) and performance is still an issue with high-res textures, but it is a lot of fun moving around.</p>
<p>Here&#8217;s what I added to Ben Joffe&#8217;s Walker:</p>
<ul>
<li>mouse control</li>
<li>strafe movement</li>
<li>walk and crouch</li>
<li>high-res textures</li>
</ul>
<p>I dropped IE-Support for this and disabled the mini map for performance reasons.</p>
<p>You&#8217;ll need <a href="http://www.google.com/chrome" target="_blank">Chrome</a>/<a href="http://code.google.com/intl/de-DE/chromium/" target="_blank">Chromium</a> to see it in action in high details mode, but it&#8217;s definitely worth it!</p>
<p><a href="http://jensarps.de/tests/canvas/textures.html" target="_blank">Go give it try!</a> Move the mouse cursor into the center of your browser window, press “M“ and enjoy!</p>
<p>PS: Chromium builds for Mac can be found <a href="http://build.chromium.org/buildbot/snapshots/chromium-rel-mac/">here</a>.</p>
<p>Note: The modifications are all just minor, all credits for this go out to <a href="http://www.benjoffe.com/">Ben Joffe</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://jensarps.de/2009/08/27/3d-canvas-walker-revisited/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
