<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

	 <channel>
	 
	 <title>Felocity.org</title>
	 <link>http://www.felocity.org</link>
	 <description>Latest entries for www.felocity.org</description>
	 <dc:language>en</dc:language>
	 <dc:creator>Jakob Heuser</dc:creator>
	 <dc:rights>Copyright 2008</dc:rights>
	 <dc:date>2008-08-31T00:35:01-08:00</dc:date>
	 <admin:generatorAgent rdf:resource="http://www.pmachine.com/" />
	 

	 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/felocity" type="application/rss+xml" /><item>
		<title>SnapTest 1.2.0 Released</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/379288788/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/snaptest_120_released/</guid>
		<description><![CDATA[
			 <p>Things have been quiet over here on the site, mostly because I've been focused on things at work and polishing up SnapTest for 1.2.0. And really, that's a good a reason as any to get the blogging going again. First and foremost, <a href="http://www.snaptest.net">SnapTest</a> 1.2.0 is out, and available for download. It comes with a slew of improvements and new things that should help make the testing process as painless as possible. Of all the things included, the most significant of these is the web testing interface.</p>

<p>I wrote recently on the topic of <a href="http://www.felocity.org/blog/article/isolation_testing_in_php/">Isolation Testing in PHP</a> as part of 1.2, and two methods are available right out of the gate. The more conventional of methods uses php's proc_open command. The web interface though takes advantage of the server to fan out processes to do work. Using the <a href="http://developer.yahoo.com/yui">YUI Library</a>, the newest version sports a web interface using the YUI Get Utility (with a callback) to ensure every PHP test runs independently. As an added bonus, on obscure windows installs where the multi-process model was pitching fits, WAMP (A and M not required) can now do full isolation testing.&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>Things have been quiet over here on the site, mostly because I've been focused on things at work and polishing up SnapTest for 1.2.0. And really, that's a good a reason as any to get the blogging going again. First and foremost, <a href="http://www.snaptest.net">SnapTest</a> 1.2.0 is out, and available for download. It comes with a slew of improvements and new things that should help make the testing process as painless as possible. Of all the things included, the most significant of these is the web testing interface.</p>

<p>I wrote recently on the topic of <a href="http://www.felocity.org/blog/article/isolation_testing_in_php/">Isolation Testing in PHP</a> as part of 1.2, and two methods are available right out of the gate. The more conventional of methods uses php's proc_open command. The web interface though takes advantage of the server to fan out processes to do work. Using the <a href="http://developer.yahoo.com/yui">YUI Library</a>, the newest version sports a web interface using the YUI Get Utility (with a callback) to ensure every PHP test runs independently. As an added bonus, on obscure windows installs where the multi-process model was pitching fits, WAMP (A and M not required) can now do full isolation testing.</p>

<p>In addition to the web interface and the command line version of multi-process support, the Mock Object engine got an overhaul with full static method support and private method inspection. Lastly, TAP support has been really improved. The output streams, tests are counted before running, and notImplemented() was changed to todo() for marking tests that haven't been done yet.</p>

<p>All in all, it's a great release, and is strongly encouraged for all users to download. The release can be picked up either through <a href="http://code.google.com/p/snaptest/downloads/list">SnapTest Google Code</a> or from <a href="http://github.com/Jakobo/snaptest/tree/1.2.0">SnapTest GitHub</a>. Happy testing.</p>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/379288788" height="1" width="1"/>]]></content:encoded>
		<dc:subject>Programming</dc:subject>
		<dc:date>2008-08-31T00:35:01-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/snaptest_120_released/</feedburner:origLink></item>

	 <item>
		<title>document.createElement and checkboxes</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/303941937/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/documentcreateelement_and_checkboxes/</guid>
		<description><![CDATA[
			 <p>I ran into a problem in building the web interface for SnapTest today, where I couldn't seem to get a checkbox to show up as checked in IE. The original code looked something like</p>

<textarea name="code" class="javascript">var cb = document.createElement(&quot;input&quot;);
cb.type = &quot;checkbox&quot;;
cb.checked = true;</textarea>

<p>And no matter how many times I tried, IE (6 specifically) refused to check the checkbox. It turns out IE want your checkboxes made in a Mozilla-incompatible way. Specifically, IE lets you call document.createElement using an entire HTML tag, which will result in a node you can perform operations on.&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>I ran into a problem in building the web interface for SnapTest today, where I couldn't seem to get a checkbox to show up as checked in IE. The original code looked something like</p>

<textarea name="code" class="javascript">var cb = document.createElement(&quot;input&quot;);
cb.type = &quot;checkbox&quot;;
cb.checked = true;</textarea>

<p>And no matter how many times I tried, IE (6 specifically) refused to check the checkbox. It turns out IE want your checkboxes made in a Mozilla-incompatible way. Specifically, IE lets you call document.createElement using an entire HTML tag, which will result in a node you can perform operations on.</p>

<p>I almost fell back on the <a href="http://dean.edwards.name/weblog/2006/11/sandbox/">conditional comment browser sniff</a> from Dean Edwards, but ended up with something I felt was much better. Everything beaten into your head about JavaScript says that feature detection is the better alternative to browser sniffing, so why not treat IE's rendering of an HTML tag as a "feature" instead of a bug.</p>

<p>A couple minutes later, I had a working solution.</p>

<textarea name="code" class="javascript">// IE requires a checkbox to be made differently
try {
    var cb = document.createElement(&quot;&lt;input type=\&quot;checkbox\&quot; checked&gt;&quot;);
}
catch (e) {
    var cb = document.createElement(&quot;input&quot;);
    cb.type = &quot;checkbox&quot;;
    cb.checked = true;
}</textarea>

<p>I guess I had never really thought of IE's bugs as features before; changing the way you can code for IE's differences from other browsers.</p>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/303941937" height="1" width="1"/>]]></content:encoded>
		<dc:subject>Programming</dc:subject>
		<dc:date>2008-06-03T19:03:00-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/documentcreateelement_and_checkboxes/</feedburner:origLink></item>

	 <item>
		<title>Isolation Testing in PHP</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/285035070/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/isolation_testing_in_php/</guid>
		<description><![CDATA[
			 <p>Since <a href="http://snaptest.googlecode.com">SnapTest 1.0</a>, I've been wanting to improve upon the level of isolation occurring on a per-test level. Working with one PHP process per file reduced the chance of collision, but it still had problems. In cases where a tested object had to work with static classes, for example, it was difficult to ensure the class was reset properly during setUp() and tearDown(). To get there, each test would need to be ran in its standalone PHP process.</p>

<p>When doing research on how to spawn sub processes cross-platform, the options end up being very limited. Since forking is not available on window boxes, the only two available options seemed to be <a href="http://www.php.net/popen">popen()</a> with STDIN and <a href="http://www.php.net/system">system()</a> with a socket connection. With inspiration from <a href="http://my2iu.blogspot.com/2006/10/javascript-in-ie-is-not-multithreaded.html">Ming's spinlock concept for JavaScript</a>, it was possible to spawn the needed child processes, and check back on their output in a round robin fashion. Using /bin/nice (or the /low switch on windows) also keeps any one process from starving the parent.&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>Since <a href="http://snaptest.googlecode.com">SnapTest 1.0</a>, I've been wanting to improve upon the level of isolation occurring on a per-test level. Working with one PHP process per file reduced the chance of collision, but it still had problems. In cases where a tested object had to work with static classes, for example, it was difficult to ensure the class was reset properly during setUp() and tearDown(). To get there, each test would need to be ran in its standalone PHP process.</p>

<p>When doing research on how to spawn sub processes cross-platform, the options end up being very limited. Since forking is not available on window boxes, the only two available options seemed to be <a href="http://www.php.net/popen">popen()</a> with STDIN and <a href="http://www.php.net/system">system()</a> with a socket connection. With inspiration from <a href="http://my2iu.blogspot.com/2006/10/javascript-in-ie-is-not-multithreaded.html">Ming's spinlock concept for JavaScript</a>, it was possible to spawn the needed child processes, and check back on their output in a round robin fashion. Using /bin/nice (or the /low switch on windows) also keeps any one process from starving the parent.</p>

<p>The final piece was building out the classes needed. Specifically, a dispatcher for managing and collecting data off of STDIN and an aggregator for handling completed result sets. The bare bones structure ended up looking a lot like a simple JavaScript event model:</p>

<textarea name="code" class="php">class Dispatcher {
    public function dispatch($call, $key_stack, $options = array()) {
        // ... set up an array for child processes
        // ... dispatch, collect round robin
        // ... got a complete response from a child
        call_user_func_array($options['thread_complete_callback'], array($results));

        // ... continue until all dispatches are made for $key_stack
        // ... dispatch complete callback
        return call_user_func_array($options['dispatch_complete_callback'], array($results));
    }
}</textarea>

<p>The final implementation ends up being a bit more verbose, but the concept is there. Unfortunately, one caveat of this approach is that call<em>user</em>func_array() is not known for its speed, as PHP isn't very good at mapping an array to function arguments.</p>

<p>The code implementation is visible in the <a href="http://github.com/Jakobo/snaptest">SnapTest repository</a> and will likely end up in the next release. The next step though is to get the web-testing interface (and then the web-services layer). AJAX makes a much better multi-process controller, and while it can only handle 4 children at once for the same domain, it does create a truly asynchronous test with all the benefits of isolation.</p>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/285035070" height="1" width="1"/>]]></content:encoded>
		<dc:subject>Programming</dc:subject>
		<dc:date>2008-05-07T01:50:00-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/isolation_testing_in_php/</feedburner:origLink></item>

	 <item>
		<title>SnapTest 1.0.0alpha and SXSW Speaking</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/218696247/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/snaptest_100alpha_and_sxsw_speaking/</guid>
		<description><![CDATA[
			 <p>I've been quiet for quite some time, although for those who know my blogging habits that shouldn't be much of a surprise. I've been head down busy with a few things, specifically preparing for South By SouthWest (I'm speaking along side some very talented people, namely <a href="http://dormando.livejournal.com">Alan Kasindorf</a> of Six Apart, <a href="http://www.romeda.org">Blaine Cook</a> of Twitter, and <a href="http://www.meebo.com">Sandy Jen</a> of Meebo. The topic is on horizontal scalability, labeled "Scalability Boot Camp". Think of it like a firehose of really useful stuff, followed by some discussion about how this all works in practical startup (and larger company) environments. For the non-technical, there will be some grounding in business concepts from Kerry Miller of BusinessWeek as the moderator. For the technical, it'll be a feast of technologies and a yummy side of deployment and technical talk. If you're going to Austin, I'll see you there!</p>

<p>The second of the housekeeping stuff actually manages to eclipse my excitement about the SXSW thing, I can actually cross something off my life-to-do list. (Not that speaking at a conference isn't on there, I just haven't spoken yet.) Instead, I'm talking about the release of an open source project which I've been working on for some time out in the open. <a href="http://snaptest.googlecode.com">SnapTest</a>, a unit testing framework for PHP, version 1.0.0 alpha is finally out. By "out" I mean there are wiki pages, documentation, and even a shiny .tar.gz waiting. While most projects I tend to do are for fun, personal benefit, this one has a certain tangibility (usefulness) to others.&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>I've been quiet for quite some time, although for those who know my blogging habits that shouldn't be much of a surprise. I've been head down busy with a few things, specifically preparing for South By SouthWest (I'm speaking along side some very talented people, namely <a href="http://dormando.livejournal.com">Alan Kasindorf</a> of Six Apart, <a href="http://www.romeda.org">Blaine Cook</a> of Twitter, and <a href="http://www.meebo.com">Sandy Jen</a> of Meebo. The topic is on horizontal scalability, labeled "Scalability Boot Camp". Think of it like a firehose of really useful stuff, followed by some discussion about how this all works in practical startup (and larger company) environments. For the non-technical, there will be some grounding in business concepts from Kerry Miller of BusinessWeek as the moderator. For the technical, it'll be a feast of technologies and a yummy side of deployment and technical talk. If you're going to Austin, I'll see you there!</p>

<p>The second of the housekeeping stuff actually manages to eclipse my excitement about the SXSW thing, I can actually cross something off my life-to-do list. (Not that speaking at a conference isn't on there, I just haven't spoken yet.) Instead, I'm talking about the release of an open source project which I've been working on for some time out in the open. <a href="http://snaptest.googlecode.com">SnapTest</a>, a unit testing framework for PHP, version 1.0.0 alpha is finally out. By "out" I mean there are wiki pages, documentation, and even a shiny .tar.gz waiting. While most projects I tend to do are for fun, personal benefit, this one has a certain tangibility (usefulness) to others.</p>

<p>I've been a big fan of Test Driven Development since I first encountered it so many years ago, but PHP was never very good at it as far as languages go. It was a bit kludgy, testing was difficult, and until PHP 5 objects were a bit of a joke.  The language has done a lot of growing up though, and with all the new OO support, PHP can support some more robust testing concepts. In many ways, Snap is also an experiment in using PHP's exception handling as a means of properly catching debug information when tests fail. While perhaps not the most elegant of solutions over magic constants like <code>__LINE__</code> and <code>__FILE__</code>, it provides a consistent interface for tracing down class, method, line, and file information in one complete package.</p>

<p>The most amazing thing is the feeling of accomplishment for getting something done. I owe a lot of thanks to Karen and Ryan for their help in building out the classes and concepts (and naming it), and for everyone who gave pointers here and there as it was developing. To the last part, you know who you were, and I'd love it if you'd all officially join the project. While I've done a collection of smaller projects, one offs, and contributed to other things before, I've never really been the lead on an OSS project before, so this is bound to be a good learning experience.</p>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/218696247" height="1" width="1"/>]]></content:encoded>
		<dc:subject>Random</dc:subject>
		<dc:date>2008-01-18T06:53:00-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/snaptest_100alpha_and_sxsw_speaking/</feedburner:origLink></item>

	 <item>
		<title>Just In Time Loader for JavaScript</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/191488208/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/just_in_time_loader_for_javascript/</guid>
		<description><![CDATA[
			 <p>Web apps are heavy, and wait times suck. For every interaction you build, there's that much more code being added to the project. Eventually, it's going to be too much for the user to handle, especially if they are on dialup or slow DSL (though I suppose even an iPhone on EDGE would qualify). For example, the Cash Shop we just launched at Gaia weighed in at over 400k (~100k gzip compressed and minified). While we're a graphic heavy site, waiting for an additional 100k was needlessly painful. To boot, there was no promise the user was <em>even going to use that feature</em>, making loading all that JavaScript and CSS a really silly exercise. We needed a way to load the JS and CSS on the fly across all browsers.</p>

<h1>Getting the JIT Loader</h1>

<p>The most recent version (1.0.0) can be downloaded here:&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>Web apps are heavy, and wait times suck. For every interaction you build, there's that much more code being added to the project. Eventually, it's going to be too much for the user to handle, especially if they are on dialup or slow DSL (though I suppose even an iPhone on EDGE would qualify). For example, the Cash Shop we just launched at Gaia weighed in at over 400k (~100k gzip compressed and minified). While we're a graphic heavy site, waiting for an additional 100k was needlessly painful. To boot, there was no promise the user was <em>even going to use that feature</em>, making loading all that JavaScript and CSS a really silly exercise. We needed a way to load the JS and CSS on the fly across all browsers.</p>

<h1>Getting the JIT Loader</h1>

<p>The most recent version (1.0.0) can be downloaded here:</p>

<p>Update: A small typo was fixed in the verifier check, but was not significant enough to throw people, so the version number hasn't been bumped. Thank you -P for catching that and sending it in.</p>

<ul>
<li><a href="http://www.felocity.org/files/jitloader/1.0.0/jitloader.js">Get the most recent JIT Loader</a> (23k)</li>
<li><a href="http://www.felocity.org/files/jitloader/1.0.0/jitloader-min.js">Get the most recent JIT Loader - min + packed</a> (5.6k)</li>
</ul>

<p>The locking utility is also included, but if <code>Lock</code> exists, it won't be used. Enough thanks can't go to <a href="http://wonko.com/article/527">Ryan Grove</a> for the original Lazy Load utility. The JIT loader, like LazyLoad is released under the New BSD License.</p>

<h1>Putting off Loading the CSS and JavaScript</h1>

<p>The method of loading we are specifically looking at is known as "event based loading" or "lazy loading". While the <a href="http://en.wikipedia.org/wiki/Lazy_loading">wikipedia article on lazy loading</a> is not very detailed, the summary of the article is that lazy loading allows us to wait on loading stuff until we need it. In computer science, usually the discussion revolves around expensive objects or data calls.  In our case, it's all about the browser load time.  There's little reason to put JavaScript or CSS into the head of a document unless we know it is 100% needed for the page.  We want to put off the expensive http connection and download as long as possible.</p>

<p>A very practical example (and one already out there) is to defer the loading of images until they are within the viewport.  Both the <a href="http://www.appelsiini.net/projects/lazyload">JQuery Lazy Load Plugin</a> and the <a href="http://developer.yahoo.com/yui/imageloader/">YUI Image Loader</a> do exactly this, reducing load times on pages by holding out on pulling down images until you need them.  For these examples, scrolling the page (and moving a placeholder into the viewport) is an event that triggers the load.  If this has proven successful for images and content, there's no reason this can't be applied to scripts and CSS as well.</p>

<h1>Loading JavaScript In Existing Frameworks</h1>

<p>To a certain extent, Dojo and YUI have both built in a loading system for including packages before executing script. They are the <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/functions-used-everywhere/dojo-require">dojo.require() directive</a> and the <a href="http://developer.yahoo.com/yui/yuiloader/">YUI Loader Utility</a> respectively. These two were specifically called out because their methods of including requested files are so different.</p>

<p>In the case of Dojo, an XMLHttpRequest (XHR) is made to load the JavaScript package, and then is ran through <code>eval()</code> to convert the request into functional code. This lets Dojo use a package style syntax similar to Java for including libraries to run. Each call to <code>require()</code> is synchronous and blocks, meaning you can trust a directive to fully complete before getting into your code. This method is highly effective for lazily loading a package since Dojo is clever enough to not include something twice. The crutch though is the XMLHttpRequest, which is subject to any cross site scripting issues. (Note: AOL has managed to do a custom Dojo build with XHR support across domains and the process is pretty well documented, but it is not the default behavior.)</p>

<p>On the other end of the spectrum, the folks at Yahoo! have taken a different approach, writing to the DOM directly using the <code>&lt;script&gt;</code> tag. This eliminates the cross browser issues that Dojo grapples with, but trades it for the limitations of inline script writing exposing the DOM to Internet Explorer in a state when it's not "complete" in IE's mind, resulting in the dreaded Operation Aborted error. In order to use the loader, there's also a lot that needs to be done if custom modules are going to be used. (As of this writing, the YUI Loader constructor does not take the config object, so it's hard to dynamically add to the object without using <code>YAHOO.lang.augment()</code>.)</p>

<p>Ryan Grove built a library independent utility for including scripts, similar to YUI, called <a href="http://wonko.com/article/527">Lazy Load</a>. It was a good strong start, and needed a steroid boost to provide the CSS support and streamlined DOM writing. Because the API and usage was radically changed, the name was changed to reflect its new usage.</p>

<h1>Just In Time Loader (JIT Loader) Basics</h1>

<p>In most situations, the behavior we are looking for is "on event X, load this, then load this, then load this, then execute Function X".  To provide access to this streamlined interface, <code>JIT.startChain()</code> was created. Calling <code>startChain()</code> returns a method-chaining object that you can use to build up a series of Javascript and CSS includes. The following methods are available on the object returned from the <code>startChain()</code> call.</p>

<ul>
<li><strong>addCss(urls, verifier, ie_version)</strong>: adds a CSS File (or array of CSS files) to the execution stack. It will continue when <strong>verifier</strong> returns true. By default, all verifiers simply make sure the nodes have been written to the DOM, not that they have been processed internally. In the case of CSS, you can specify a specific IE version you want to apply this CSS to in order to keep your CSS files clean.</li>
<li><strong>load(urls, verifier)</strong>: adds a JavaScript file to the execution stack</li>
<li><strong>loadOnce(urls, verifier)</strong>: adds a JavaScript file to the execution stack. When fired, if the URL has already been added by another JIT load or an external source, it won't be loaded again.</li>
<li><strong>onComplete(function, obj, scope)</strong>: Starts the execution chain. When the execution chain has completed, <strong>function</strong> will be ran. If <strong>obj</strong> is suppled, it will be passed as an argument. If <strong>scope</strong> is true, <strong>function</strong> will instead be directly ran in the context of <strong>obj</strong>.</li>
</ul>

<p>The most primitive example of chaining would then look something like:</p>

<textarea name="code" class="javascript">JIT.startChain().
loadOnce(jsfile, function() { /* verifier */ }).
addCSS(cssfile).
onComplete(function() {
    // run this when everything is loaded
});</textarea>

<p>If chaining is not your thing, you can also make direct calls to the JIT object (see examples at the end). After the verifier, each of the above calls takes a callback function, object, and scope; the <code>onComplete()</code> doesn't exist in the root JIT object and is used solely for the purposes of chaining.  These are left available in case more advanced functionality is required.</p>

<h1>Optimizations</h1>

<p>Because JavaScript is (mostly) single threaded, if there are multiple calls to the Lazy Loader, we shouldn't wait on the current code execution block to write to the DOM and clean up when it is finished. The original Lazy Load used a queue system that let multiple calls stack as pending, even if they were for different load requests. The smallest synchronous operation is the DOM write, which can be pushed out to a method and can be locked using a <a href="http://www.felocity.org/blog/article/javascripts_strange_threaded_nature">spinlock to emulate fake threads</a>. Any events that get queued up between DOM writes can be added to the stack, and can then execute while slow scripts take a while. This speedup is surprisingly most noticeable on Internet Explorer, where events are allowed to interrupt the current JavaScript thread, to write more concurrent nodes into the DOM.</p>

<h1>Limitations</h1>

<p>The verifier function that is passed in is the linchpin of the event based loading. When the verifier resolves to <code>true</code>, the loading process continues with the assigned callback. When working with CSS, this is exceptionally difficult. There are two options when dealing with event loading the CSS files, either find a testable property in the CSS, or pass in <code>null</code> for the verifier slot, and load the CSS first.  While the first offers more reliability, the second tends to be more practical, since the CSS won't usually apply to anything other than nodes created by the JavaScript. A simple example of a CSS verifier would be (assuming your CSS sets the body's background image to the below mentioned URL:</p>

<textarea name="code" class="javascript">var verifier = function() {
    return (document &amp;&amp; document.body &amp;&amp; document.body.backgroundImage = &quot;http://example.com/load_complete.gif&quot;) ? true : false;
}</textarea>

<p>The second major limitation of the system is in <code>loadOnce()</code> which requires script nodes to exist in the DOM to test if they have been properly loaded. This testing method makes it incompatible with the <code>dojo.require()</code> directive which uses the XHR to perform script includes.  In the future, the verifier check might be ran once to preemptively test for component loading, but that will cause issues with testing in the <code>YAHOO</code> namespace.</p>

<h1>Enough Already, Examples Please!</h1>

<p>If you've had enough reading, here's some examples of JIT being used:</p>

<ul>
<li><a href="http://www.felocity.org/files/jitloader/examples/slow_script_example.html">Multiple Calls, Slow Server</a>: Multiple JIT calls, where the call chain is intentionally stalled. Makes it possible to see how IE can optimize the load calls.</li>
<li><a href="http://www.felocity.org/files/jitloader/examples/proximity_example.html">Proximity Loading</a>: Using a precursor event to start loading as quickly as possible. Clicking on the button starts a load chain (which will always be one step behind) with a show command on the end. This demonstrates using a user's likely behavior to prepare incoming JS.</li>
<li><a href="http://www.felocity.org/files/jitloader/examples/direct_usage_example.html">Advanced Direct Usage</a>: For direct access to the JIT object, more intricate behaviors can be built, for example, pausing the include to run JavaScript, then resuming the includes.</li>
</ul>

<p>You can also see JIT in use on the website <a href="http://www.gaiaonline.com">Gaia Online</a> for the Cash Shop (under the market submenu) and eventually in place for the world map and other header-based events.</p>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/191488208" height="1" width="1"/>]]></content:encoded>
		<dc:subject>Programming</dc:subject>
		<dc:date>2007-11-27T21:42:00-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/just_in_time_loader_for_javascript/</feedburner:origLink></item>

	 <item>
		<title>Javascript’s Strange Threaded Nature</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/181877052/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/javascripts_strange_threaded_nature/</guid>
		<description><![CDATA[
			 <p>There's a lot of digging required to figure out if Javascript is single or multi-threaded, and for every article out there, at least three contradict it. Thanks to the work Dan Simard in June, <a href="http://www.javascriptkata.com/2007/06/12/ajax-javascript-and-threads-the-final-truth/">a final answer on Javascript threads</a> was reached. The only major problem in this was that the comments by a user to Simard's post indicated that <code>alert()</code> caused Firefox's execution chain to change. The result was while the prompt was on screen, <code>setTimeout()</code> and other assorted callback functions were free to resolve.</p>

<p>The problem is made worse with several <code>setTimeout()</code> calls. As a single thread, JavaScript maintains some sort of event stack, where all of the callbacks and timeouts pile up, waiting for their turn. Once the event stack is out of events, the timers start again to count down to execution. If you fire one call with a <code>setTimeout()</code> and a timeout value of 2 seconds, and one more second of code execution follows, there will still be 2 seconds on the timer since it has not had a chance to run.&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>There's a lot of digging required to figure out if Javascript is single or multi-threaded, and for every article out there, at least three contradict it. Thanks to the work Dan Simard in June, <a href="http://www.javascriptkata.com/2007/06/12/ajax-javascript-and-threads-the-final-truth/">a final answer on Javascript threads</a> was reached. The only major problem in this was that the comments by a user to Simard's post indicated that <code>alert()</code> caused Firefox's execution chain to change. The result was while the prompt was on screen, <code>setTimeout()</code> and other assorted callback functions were free to resolve.</p>

<p>The problem is made worse with several <code>setTimeout()</code> calls. As a single thread, JavaScript maintains some sort of event stack, where all of the callbacks and timeouts pile up, waiting for their turn. Once the event stack is out of events, the timers start again to count down to execution. If you fire one call with a <code>setTimeout()</code> and a timeout value of 2 seconds, and one more second of code execution follows, there will still be 2 seconds on the timer since it has not had a chance to run.</p>

<textarea name="code" class="javascript">var foo_count = 0;
var bar_count = 0;
var foo = function() {
    ++foo_count;
    window.setTimeout(bar, 5);
};
var bar = function() {
    ++bar_count;
    alert(&quot;foo=&quot;+foo_count+&quot;, bar=&quot;+bar_count);
};

// triggers
window.setTimeout(foo, 10);
window.setTimeout(bar, 20);
// end triggers</textarea>

<p>In a perfectly timed environment (running just this code), foo will execute, followed by bar, followed by foo's call to bar. In reality, the ms calibration for this is iffy. The output comes out as <strong>foo=1, bar=2</strong> then <strong>foo=1, bar=1</strong>. However, simply looking at the timing values, our alert calls should be reversed. We've entered the world of volatile variables and shared space without even knowing (and probably not even wanting). Under the hood, it appears that making a call to <code>alert()</code>, <code>prompt()</code>, <code>confirm()</code>, or any other window level call pauses the current thread's execution, letting any pending <code>setTimeout()</code> calls resolve.  When the execution returns from the window event, variables that were scoped one block higher could have changed without the knowledge of the current execution block.</p>

<p>A more practical example of this can be found on the <a href="http://www.felocity.org/media/2007/10/26-threadsafe_js/example.html">Threadsafe JS Example Page</a>. As of this writing, IE and Opera execute things properly in order, waiting for the <code>prompt()</code> to finish before continuing the current code block, and after completion, letting the pending <code>setTimeout()</code> event fire. In Firefox and Safari, during the <code>prompt()</code> call, the <code>setTimeout()</code> executes, overwriting the value of <code>bar</code>.</p>

<h1>Protecting A Volatile Bar</h1>

<p>As mentioned before, when the browser's JS Interpreter hands off to the <code>alert()</code>, it begins resolving any waiting <code>setTimeout()</code> calls that in in the event queue. In our example, another call to <code>bar()</code> is waiting which also increments <code>bar_count</code>.  By the time we alert <code>bar_count</code>, something has gone and changed it. This seems to also hold true for <code>prompt()</code> and <code>confirm()</code> in Firefox and a few other browsers.</p>

<p>Imagine instead of just our primitive <code>window.setTimeout()</code> we were using an AJAX callback which waited for a DOM node to be available. The costs of this shared variable space being violated is a bit more costly. In many other languages, there are Mutexes the <code>synchronized</code> call, and the <code>volatile</code> declarative.  Because the implementation of ECMA is unique to each browser, there needs to be a consistent way to secure data from tampering during the application's critical moments.</p>

<p>At our disposal is the following JavaScript knowledge:</p>

<ul>
<li><code>new Object()</code> is atomic (can't be interrupted by browser events)</li>
<li><code>return (new Object() === new Object());</code> is always false as each new object is given a unique ID by the system. We need a way to atomically create an ID for a fake thread.</li>
<li><code>Array.push()</code> is atomic (can't be interrupted by browser events) as long as we are using the native implementation. This non blocking implementation means even if two events get in the way of each other, only one will hold index[0] in the final array</li>
<li><code>(function() { new Object(); })();</code> is garbage collected properly</li>
<li>block scope level variables cannot be changed by outside factors</li>
</ul>

<p>That doesn't leave us with much. <a href="http://my2iu.blogspot.com/2006/10/javascript-mutexes-2.html">Ming made a post on JS Mutexes</a> that got the ideas flowing. The biggest concern from Ming's entries was that in Internet Explorer, events such as onload can interrupt a process, creating multiple events at the same time. To get around this, we would need a method which the browser cannot interrupt. This is where the native <code>Array.push()</code> comes in handy. For some reason, IE treats this call as non-interruptable, letting us have a queue process that ensures element 0 is the first lock requester. If we have two atomic commands, one to uniquely identify a lock request and another to enqueue the lock, then we have everything we need for a very basic spinlock implementation. Even if a second event interrupts our two statements, the pushing onto the array guarantees only one of the two requests will be given rights to the lock.</p>

<p>Spinlock design implies a "busy wait" cycle for getting the lock, meaning each individual thread usually sits in the equivalent of <code>while(1) {}</code>.  Because we don't have threads and instead have the event queue, a while loop would seize the system.  To get around this, we can use the same <code>setTimeout()</code> call that was the source of our problem to "sleep" an event until the lock resource is available. The result is a very lazy locking method that requires the application to care about the lock (but a lock that can be used in many different ways).  Our pseudo code looks like:</p>

<textarea name="code" class="pseudo">sub process
    lock = get lock
    if not lock owner
        retry sub process in N ms (sleep)
        return

    lock was obtained
    perform critical code
    release lock

    non critical segment here
end process</textarea>

<p>Return to the <a href="http://www.felocity.org/media/2007/10/26-threadsafe_js/example.html">Threadsafe Test</a> and try the protected version. Across all browsers, the lock is held until the process has properly completed.</p>

<h1>Beyond Locking Down Variables</h1>

<p>A locking system like this can be extended to deal with more than just the Javascript Variables. In the case of lazy loading javascript, it is possible to be using the same utility to load several "sets" of Javascript at the same time.  To avoid keeping the document.head open (and risking Operation Aborted problems), we use the same locking strategy to keep a DOM node from getting written to until Internet Explorer reports it as closed, such as an onreadystate for a script tags.</p>

<p>The locking utility can also be used to create "run once" functions such as an init() for a class outside of its constructor.  The class can simply request the lock, and on completion, refuse to release it. While this takes up a small bit of memory in the lock utility, it also guarantees only one <code>init()</code> reaches the critical section for the life of the page.</p>

<h1>Limitations</h1>

<p>Building such a locking system in JavaScript is not without drawbacks. The most notable of these is the lack of support for browsers which do not support <code>Array.push()</code>. If this browser needs to be supported, there's not much that can be done via this method, or you can simply take your chances and code with very clear and isolated callbacks and timeouts.</p>

<p>It's also unknown just how atomic the methods are. While in brief tests in Rhino this appears to be atomic during the critical push step, there's no guarantee that it is actually going to be atomic if the browser makers create true Multi-Threaded JavaScript. Hopefully by then, there will also be the <code>volatile</code> keyword.</p>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/181877052" height="1" width="1"/>]]></content:encoded>
		<dc:subject>Programming</dc:subject>
		<dc:date>2007-11-08T21:38:00-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/javascripts_strange_threaded_nature/</feedburner:origLink></item>

	 <item>
		<title>Git-Svn on OSX</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/141486117/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/git_svn_on_osx/</guid>
		<description><![CDATA[
			 <p>Getting both <a href="http://git.or.cz/">Git</a> and <a href="http://subversion.tigris.org/">Subversion</a> to play nicely on OSX is a feat and a half.  I spent the last few weeks fighting with the default install of Perl (outdated 5.8.6), bindings, CPAN, and a mess of port options just to get git-svn working properly.  Why would I want to use git-svn?  Well, a project that's been in the works for a bit has finally made its way onto Google Code, which uses SVN for source control.  This is a great thing, aside from the fundamental problem in SVN, which is commit access and trust networks.  There are people who can explain the <a href="http://git.or.cz/gitwiki/LinusTalk200705Transcript">shortfalls of Subversion</a> better than me.  More importantly, once you've decided that distributed source control is a valuable thing and want to use it on your Mac, you're in for a whirlwind of excitement.  Hopefully, this step by step guide will iron out the kinks and get you running git-svn in no time.</p>

<h2>Step 1: Getting MacPorts, Installing Base Software</h2>

<p><strong>Update Aug 08:</strong> It was pointed out that you need the OSX Developer Tools installed. They are on the OSX CD, and enable the ability to compile things.  It's a must have for this to work.&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>Getting both <a href="http://git.or.cz/">Git</a> and <a href="http://subversion.tigris.org/">Subversion</a> to play nicely on OSX is a feat and a half.  I spent the last few weeks fighting with the default install of Perl (outdated 5.8.6), bindings, CPAN, and a mess of port options just to get git-svn working properly.  Why would I want to use git-svn?  Well, a project that's been in the works for a bit has finally made its way onto Google Code, which uses SVN for source control.  This is a great thing, aside from the fundamental problem in SVN, which is commit access and trust networks.  There are people who can explain the <a href="http://git.or.cz/gitwiki/LinusTalk200705Transcript">shortfalls of Subversion</a> better than me.  More importantly, once you've decided that distributed source control is a valuable thing and want to use it on your Mac, you're in for a whirlwind of excitement.  Hopefully, this step by step guide will iron out the kinks and get you running git-svn in no time.</p>

<h2>Step 1: Getting MacPorts, Installing Base Software</h2>

<p><strong>Update Aug 08:</strong> It was pointed out that you need the OSX Developer Tools installed. They are on the OSX CD, and enable the ability to compile things.  It's a must have for this to work.</p>

<p>We're skipping the Fink v MacPorts (formerly Darwinports) discussion completely.  The simple answer for this is that MacPorts has the builds we need at the versions we want.  You're more than welcome to tackle this with Fink, as the concept will be identical.  The absolute first thing you need to do is grab the <a href="http://darwinports.com/download/">MacPorts installer</a> and get it up and running.  Open the .dmg file, install, open a Terminal window, and run:</p>

<textarea name="code" class="sh">$&gt; sudo port -d selfupdate</textarea>

<p>This will bring MacPorts up to date, and ready to do the installs.  To get git-svn up and running, we'll need ultimately Git (1.5.2.3), Subversion (1.4.4), and the dependancies for the SVN/Perl Bindings.  With the ports collection installed, we'll install the Git Core, Subversion, and SWIG (a dependancy for the perl bindings).</p>

<textarea name="code" class="sh">$&gt; sudo port install git-core
$&gt; sudo port install subversion
$&gt; sudo port install swig</textarea>

<p>Yikes, that's a lot of dependancies!  That's okay though, the ports collection will handle adding everything you need. As an added bonus, it will all be in /opt/local, meaning your normal OSX software remains untouched.  Once up and running, you'll notice that the version of Git provided by MacPorts is slightly out of date.  We can fix that, but at least all the dependancies are now in place.  From here, we can build our missing gaps from source files.</p>

<h2>Step 2: Build from Source</h2>

<p>We'll need to download the latest <a href="http://git.or.cz/">Git</a> and proper <a href="http://subversion.tigris.org/">Subversion</a>.  Go grab those tar.gz files, and take care to match up your Subversion download to the version installed by MacPorts.  You can find that by entering at the Terminal:</p>

<textarea name="code" class="sh">$&gt;svn --version</textarea>

<p>You'll need at least Subversion 1.4.4 for this to work, although I'm sure newer revisions would work as well.  With both downloaded, we'll install first Git, and then the Subversion Perl bindings.  Open a Terminal window, cd to the location of your Git download, untar it, and run the following commands</p>

<textarea name="code" class="sh">$&gt; make configure
$&gt; ./configure --prefix=/opt/local
$&gt; sudo make install</textarea>

<p>By setting the prefix to /opt/local, we'll overwrite the current Git install with our new version, including the new git-svn scripts we'll be wanting.  Attempting to run it though informs us that the svn-swig libraries are not in place yet.  We'll need to make those.</p>

<p>We won't be installing all of Subversion.  Instead, we will be going all the way up to the install step and stopping.  This way, we have the svn binary, working swig and neon paths (we won't care that autoconf says our neon is "too new"), and the original OSX version of Perl which has the really wacky library paths.  Thankfully, OSX also is smart enough to put our libraries in the right spots.  Change directory to the Subversion download, untar, and run the following</p>

<textarea name="code" class="sh">$&gt; ./configure --prefix=/opt/local
$&gt; make
$&gt; make swig-pl
$&gt; make check-swig-pl
$&gt; sudo make install-swig-pl</textarea>

<p>Like Git, we'll put it in /opt/local.  That will fill out any of the problems we were having with the Perl libraries being in the wrong place (or not existing at all).  You could try to install Perl 5.8 from ports as well (in fact, trying to install subversion-perlbindings forces it), but every time I had two sets of Perl on OSX, things got a bit strange.  Once complete, you can test your install with</p>

<textarea name="code" class="sh">$&gt; git --version
git version 1.5.2.3
$&gt; git-svn --version
git-svn version 1.5.2.3 (svn 1.4.4)</textarea>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/141486117" height="1" width="1"/>]]></content:encoded>
		<dc:subject>Programming</dc:subject>
		<dc:date>2007-08-07T05:55:00-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/git_svn_on_osx/</feedburner:origLink></item>

	 <item>
		<title>Defining Social Fun</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/130324695/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/defining_social_fun/</guid>
		<description><![CDATA[
			 <p>In professional talks about Gaia Online, I've been asked the question "what makes your users so passionate?" although never in such a direct way.  Usually, the questions are "how does the site sustain itself?", "what is there to do on the site?", and "how do you have that many people?" Everyone always seems amazed at the volume of users that are on Gaia at any one time; there was a record 86,738 users online a few months ago (January 4), and we cleared the 5 million registration mark awhile ago.  The site's addictive in a way that has never been explained.  There's a magic "secret sauce" at work- a sauce that Newsvine has picked up on, that MySpace didn't know they had, and that Gaia Online happily cultivates.  In each site's own way- it's fun.  Now, if only it was possible to qualify what exactly "fun" means, then everyone would have an awesome community website.  Try and define fun by itself though, and the result is a meaningless description that certainly can't be coded.</p>

<h1>Beyond "Fun"</h1>

<p>The concept of fun is so confusing, that the more a person tries to define it, the more confusing the concept becomes.  Instead, fun is better described as a summation of things; interestingly, these things in and of themselves are not necessarily fun, but instead are foundations of an online emulation of life.  In 1943, Maslow created a <a href="http://en.wikipedia.org/wiki/Maslow's_hierarchy_of_needs">Hierarchy of Needs</a>, which described the basic needs of human beings.  Later, Nevis revised this theory slightly, adapting it based on his studies of East Asian values.&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>In professional talks about Gaia Online, I've been asked the question "what makes your users so passionate?" although never in such a direct way.  Usually, the questions are "how does the site sustain itself?", "what is there to do on the site?", and "how do you have that many people?" Everyone always seems amazed at the volume of users that are on Gaia at any one time; there was a record 86,738 users online a few months ago (January 4), and we cleared the 5 million registration mark awhile ago.  The site's addictive in a way that has never been explained.  There's a magic "secret sauce" at work- a sauce that Newsvine has picked up on, that MySpace didn't know they had, and that Gaia Online happily cultivates.  In each site's own way- it's fun.  Now, if only it was possible to qualify what exactly "fun" means, then everyone would have an awesome community website.  Try and define fun by itself though, and the result is a meaningless description that certainly can't be coded.</p>

<h1>Beyond "Fun"</h1>

<p>The concept of fun is so confusing, that the more a person tries to define it, the more confusing the concept becomes.  Instead, fun is better described as a summation of things; interestingly, these things in and of themselves are not necessarily fun, but instead are foundations of an online emulation of life.  In 1943, Maslow created a <a href="http://en.wikipedia.org/wiki/Maslow's_hierarchy_of_needs">Hierarchy of Needs</a>, which described the basic needs of human beings.  Later, Nevis revised this theory slightly, adapting it based on his studies of East Asian values.</p>

<table>
    <tr>
        <th>Maslow</th>
        <th>Nevis</th>
    </tr>
    <tr>
        <td>Self-Actualization</td>
        <td>Self-Actualization (non ego)</td>
    </tr>
    <tr>
        <td>Esteem</td>
        <td>Safety</td>
    </tr>
    <tr>
        <td>Love/Belonging</td>
        <td>Physiology</td>
    </tr>
    <tr>
        <td>Safety</td>
        <td>Belonging</td>
    </tr>
    <tr>
        <td>Physiological</td>
        <td></td>
    </tr>
</table>

<p>We can assume that because visitors to community websites have access to the Internet, they also have their physiological and safety needs met.  This leaves "belonging" as the common denominator of needs between both Maslow and Nevis' studies.  It can be concluded then that "fun", is the combination of a sense of belonging, a venue for satisfying esteem, and ultimately achieving a state of self-actualization.  When all three needs are met, as the sites we will be discussing show, users have a higher retention rate, contribute to the larger community as a whole, and become evangelists of the site in question.  They become passionate users.</p>

<h1>The Sites Being Talked About</h1>

<p><a href="http://www.gaiaonline.com">Gaia Online</a>: Gaia Online labels itself as the premier social hangout for teenagers, with the largest forums on the Internet, several games, and a customizable avatar system. (<strong>Disclaimer</strong> As of this writing, I am employed by Gaia Interactive, creators of Gaia Online.)</p>

<p><a href="http://www.newsvine.com">Newsvine</a>: "Get Smarter Here" is the tagline for the online news site that is rapidly growing in popularity.  Its primary features include commenting and voting on news stories, as well as a "Doppleganger" technology which can harvest information off of the popular newswire services.  Members can run their own columns or get together and form groups to produce their own online focused mini news sites.</p>

<h1>The Most Common Need: Belonging</h1>

<p>As mentioned above, the most common need expressed across both hierarchies is the need to belong.  Belonging in the most literal sense means to feel a part of a group.  A very basic belonging can be achieved in simple groupings of interests, likes, and dislikes. <img src="http://www.felocity.org/media/2007/01/11-social_need_media/newsvine_seeds.png" alt="Newsvine Top Seeds" title="Newsvine Top Seeds are relevant to the category you are browsing" /> Newsvine, for example, makes it easy for readers browsing by a category of interest to immediately locate people who are talking and writing about related topics.  Thanks to Newsvine's weighting technology, there's a high chance the articles found will be interesting and the users will return once, then twice, then thrice.  Eventually, the users will keep returning since the articles the users finds are of value to them.  They have achieved belonging and are ready to contribute to the collective group.</p>

<p>Gaia Online doesn't have the direct categories of Newsvine, and therefore depends on the more conventional social networking means.  Through forums, profiles, and journals, users communicate with each other while sharing a common goal- the quest for virtual items to improve their online avatar.  While this isn't always a driving force behind users' site activity, it's a commonality all users on the site share, so users start interacting primarily for the gold.  They play games, post, vote in arenas, and ultimately find their first friends on the site.  When this happens, users find their "home", a thread or two they always return to where most of their friends are chatting.  That first connection and those first friends create a strong sense of belonging, as those friends will often pull the new users into their favorite threads and hangouts, immersing them in a smaller subset of the Gaia community.</p>

<p>Some popular social networking sites achieve belonging by creating locations central to a users' network of friends.  This sense of belonging users get is no less valid than those previously mentioned.  However, the sense of belonging becomes very dependent on the users' primary network to remain on the site/service.  A very solid case that illustrates this belonging pattern is <a href="http://www.facebook.com">Facebook</a> and its "seasonal disorder".  Before Facebook started broadening its audience outside of the college community, a wave pattern could be identified in the site's average traffic, with dead times in the summer and surges in the fall.  This corresponded with the typical academic calendar.  Additionally, as students moved through their final year of college, their "belonging" on Facebook faded.  The use of Facebook as a tool for class information, parties, and networking became less valuable as the users' friends also stopped using the service.  This resulted in a constant amount of attrition which ate away at any longevity the site hoped to achieve.</p>

<h1>After You Belong</h1>

<p>Continuing with the pyramid of needs outlined above, when users of a site have achieved a sense of belonging, the next tiers of esteem and self-actualization become available.  In Western cultures, esteem is a highly valuable component of a community's success.  People who feel they have accomplished something socially return to the places that make them feel better.  Still, esteem isn't just about popularity, although being popular in the context of the community is certainly a draw.  A site that promotes a sense of self-rewarding can also further a users' esteem.  Much like how people who play MMORPGs feel proud of their characters, people who participate in communities feel good about their contributions.  Following this logic, sites that make users feel good about their contributions will have users who contribute more.  One popular method to measure a users' contributions is with a karma system.  Newsvine has taken it a step further with its [Vinacity][vineacity] system, which takes the traditional +/- karma system, and rewards users based on their participation on the site.  As users post, comment, and participate, pieces of their vine fill up, providing an outward status icon to the community of their accomplishments.</p>

<p>Gaia, like many other community/game hybrid sites, reflects esteem through the collection of the game's items or status symbols.  Much how the vine plaque of Newsvine indicates someone's contributions to the community, a large amount of virtual wealth and item-based accomplishments can also provide a point for esteem.  One of the most common activities on Gaia is the process of "questing," which has little to do with the MMORPG concept, but instead is a way for users to share their progress toward an expensive item on the site.  During the quest, the users provide updates, take donations, and ask the community for help and support.  Other members help out, and eventually the users' goal is reached.  That item they acquired then becomes a symbol of status they wear proudly.  As users participate in the site and accrue items and virtual wealth, they also achieve a sense of accomplishment.  In both Gaia and Newsvine's cases, users feels like they belong, and feel good about their activity.  At this point, it's safe to say they are regular users.  All they need is something that makes them want to evangelize the site.</p>

<h1>From Regular to Evangelist</h1>

<p>Adding more ways to build esteem and provide opportunities for users to belong is not enough to promote a regular user to an evangelical one.  Instead, users who are passionate about a site had an event which has pushed them from the point of being regular users to the point of telling others actively.  There are several contributing factors which can collectively drive users to this point (in no specific order):</p>

<ul>
<li>Enjoyment of the site's experience</li>
<li>Enjoyment of the people on the site</li>
<li>Kicking-Ass at something</li>
<li>Explaining the to others and what makes it fun</li>
</ul>

<p>Beyond this, coming together in real life can accelerate this process greatly.  Taking the online community "offline" puts faces and real names to friends who were once only pixels, and the site becomes a common ground.  The <a href="http://spring.newsvine.com/_news/2006/05/30/234195-the-first-newsvine-charity-event">Newsvine Relay For Life</a> was the first community-wide event, that brought individuals together in real life while supporting the American Cancer Society.  Those who participated still remain some of the site's most active users.  The events that bring forth a "Random Act of Vineyness" (the highest honor at Newsvine) come with dozens of users who have taken an online experience and turned it into something personal and important to them.  In short, it made a difference in their lives.</p>

<p>At Gaia, we see how we change people's lives all the time through the letters that we get and at the conventions that we attend.  We've seen people who used our community to break drug addiction, find friends, and become better people.  We've also seen the people who help community members selflessly in our Life Issues forum, and donate to the previously-mentioned quests.  At the convention, these people get to meet for the first time.  In the years I've been with the company, it's happened hundreds of times; people meet at the Gaia booth, shriek, hug, and then spend the next thirty minutes to an hour talking about the website.  At conventions the users' real lives are brought back to their virtual ones with the ability to play real life games to gain virtual items for their avatars.  The <a href="http://www.youtube.com/watch?v=RZozJ20gZok">Gaia Panel</a> experience is also amazing. A small section of the community comes together for two hours to talk about features, voice complaints, and ask questions.  In this offline space, users feels responsible for the development of the website, and as stakeholders, take a deep interest in it.</p>

<h1>So is it Kool-Aid?</h1>

<p>Like Maslow's pyramid, a community site's success should be built from the foundation up.  Deep moments of connection cannot occur until the prerequisite experiences of belonging and esteem are fulfilled. The end goal is to make something important to people and to make their experience "fun."  When the social networking cloud settles, it's on these sites that the users will continue to invest their time.</p>

<h1>References</h1>

<p>Harlow, <a href="http://psychclassics.yorku.ca/Harlow/love.htm">The Nature of Love</a></p>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/130324695" height="1" width="1"/>]]></content:encoded>
		<dc:subject>Random</dc:subject>
		<dc:date>2007-03-04T08:25:00-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/defining_social_fun/</feedburner:origLink></item>

	 <item>
		<title>Stylizing the Form Submit Button</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/130324696/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/stylizing_the_form_submit_button/</guid>
		<description><![CDATA[
			 <p>"The buttons aren't styling" I remarked as I stared at the page in Camino and Safari.  Testing on the Mac platform has been the absolute bane of my existence as of late, mostly because for some reason, these browsers in particular are very protective of their form widgets.  Coming back to <a href="http://themaninblue.com/writing/perspective/2004/04/28/">Cameron Adams' Entry on Styling Form Widgets</a>, I found that none of the Macromedia examples were actually working for Camino/Safari, although they looked beautiful in Firefox.  The submit button simply would not take the background settings.  Interesting enough though, something of <code>input type="button"</code> styled perfectly.</p>

<p>However, the <code>value</code> attribute of the button wasn't getting passed in.  For the legacy code around Gaia, we have forms with more than one possible "submit" for an action.  The most common case of this is preview and submit buttons we traditionally use in the forums.  This left us with two scenarios:&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>"The buttons aren't styling" I remarked as I stared at the page in Camino and Safari.  Testing on the Mac platform has been the absolute bane of my existence as of late, mostly because for some reason, these browsers in particular are very protective of their form widgets.  Coming back to <a href="http://themaninblue.com/writing/perspective/2004/04/28/">Cameron Adams' Entry on Styling Form Widgets</a>, I found that none of the Macromedia examples were actually working for Camino/Safari, although they looked beautiful in Firefox.  The submit button simply would not take the background settings.  Interesting enough though, something of <code>input type="button"</code> styled perfectly.</p>

<p>However, the <code>value</code> attribute of the button wasn't getting passed in.  For the legacy code around Gaia, we have forms with more than one possible "submit" for an action.  The most common case of this is preview and submit buttons we traditionally use in the forums.  This left us with two scenarios:</p>

<p>Submit Buttons that couldn't be styled in Camino / Safari</p>

<textarea name="code" class="html">&lt;form id =&quot;myForm&quot; action=&quot;some.php&quot; method=&quot;POST&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;foo&quot; value=&quot;&quot;/&gt;
    &lt;input id=&quot;submitBar&quot; type=&quot;submit&quot; name=&quot;action&quot; value=&quot;bar&quot; /&gt;
    &lt;input id=&quot;submitBaz&quot; type=&quot;submit&quot; name=&quot;action&quot; value=&quot;baz&quot; /&gt;
&lt;/form&gt;</textarea>

<p>or Button tags that wouldn't pass in their <code>value</code> to the PHP script (and shouldn't technically perform a submit either)</p>

<textarea name="code" class="html">&lt;form id =&quot;myForm&quot; action=&quot;some.php&quot; method=&quot;POST&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;foo&quot; value=&quot;&quot;/&gt;
    &lt;input id=&quot;submitBar&quot; type=&quot;button&quot; name=&quot;action&quot; value=&quot;bar&quot; /&gt;
    &lt;input id=&quot;submitBaz&quot; type=&quot;button&quot; name=&quot;action&quot; value=&quot;baz&quot; /&gt;
&lt;/form&gt;</textarea>

<p>The final solution ended up being something right down the middle and using JavaScript to make up for Safari / Camino's shortcomings.  Starting with a default submit button, we can replace it with a <code>input type="button"</code> node, and add a bit of JavaScript to the <code>onclick</code> to make up for the stylized button's shortcomings.  The first block of JavaScript goes into the <code>HEAD</code>, and the second block can either go into an onLoad handler or at the end of the form tag, depending on how soon you need the replacement.</p>

<textarea name="code" class="javascript">////////
// SwapSubmit - A Tool for Stylizing Submit Buttons on All Browsers
// Licensed under CC-GPL-2.0
// http://creativecommons.org/licenses/GPL/2.0/
////////
var RJH_SwapSubmit = {
    replacedEles: new Object(),
    replace: function(formid, eleid) {
        if (typeof eleid == &quot;string&quot;) var ele = document.getElementById(eleid);
        else var ele = eleid;

        if (typeof formid == &quot;string&quot;)  var f = document.getElementById(formid);
        else var f = formid;

        if (ele)
        {
            var o = this.build(formid, ele);
            var name = ele.getAttribute(&quot;name&quot;);
            var value = ele.getAttribute(&quot;value&quot;);

            var pn = ele.parentNode;
            pn.removeChild(ele);
            pn.appendChild(o);

            if (!document.getElementById(name)) f.appendChild(this.buildInputField(formid, name));

            this.replacedEles[eleid] = new Object();
            this.replacedEles[eleid][&quot;name&quot;] = name;
            this.replacedEles[eleid][&quot;value&quot;] = value;
            this.replacedEles[eleid][&quot;form&quot;] = formid;
        }

    },
    build: function(formid, ele) {
        var o = document.createElement(&quot;button&quot;);
        var f = document.getElementById(formid);

        var oldOnclick = ele.onclick;
        o.id = ele.id;
        o.className = ele.className;
        o.onclick = function() {
            if (oldOnclick) {
                if(oldOnclick() == false) return false;
            }
            RJH_SwapSubmit.submitForm(this);
        };

        return o;
    },
    buildInputField: function(formid, name) {
        var o = document.createElement(&quot;input&quot;);

        o.setAttribute(&quot;type&quot;, &quot;hidden&quot;);
        o.id = name;
        o.setAttribute(&quot;name&quot;, name);

        return o;
    },

    // ORIGIN: onClick of a button
    submitForm: function(ele) {
        var clickId = ele.id;
        var name = RJH_SwapSubmit.replacedEles[clickId][&quot;name&quot;];
        var value = RJH_SwapSubmit.replacedEles[clickId][&quot;value&quot;];
        var formid = RJH_SwapSubmit.replacedEles[clickId][&quot;form&quot;];
        document.getElementById(name).value = value;
        document.getElementById(formid).submit();
    }
};</textarea>

<textarea name="code" class="javascript">RJH_SwapSubmit.replace(&quot;FORMID&quot;, &quot;SUBMITBBUTTONID&quot;);</textarea>

<p>Replace FORMID and SUBMITBUTTONID with the relevant values.  If you want to see it in action, check out a <a href="http://www.felocity.org/media/2006/10/28-stylized_buttons">working example</a>.  The example will also echo out the form contents on submit.  You'll have to forgive the poor PNG buttons.</p>

<h2>Drawbacks</h2>

<p>The largest drawback hands down is the addition of JavaScript.  It's not something to depend on, and many steps were taken to ensure that the enhancement is progressive in nature.</p>

<p>Styled images will have to be styled to reflect the change from an <code>input</code> to a <code>button</code> node, and can be referenced via <code>button#idNameofElement</code> to apply all the necessary stylization.</p>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/130324696" height="1" width="1"/>]]></content:encoded>
		<dc:subject>GaiaOnline, Programming</dc:subject>
		<dc:date>2006-10-28T21:20:00-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/stylizing_the_form_submit_button/</feedburner:origLink></item>

	 <item>
		<title>PHP Transaction Manager Architecture</title>
		<link>http://feeds.feedburner.com/~r/felocity/~3/130324697/</link>
		<guid isPermaLink="false">http://www.felocity.org/blog/article/php_transaction_manager_architecture/</guid>
		<description><![CDATA[
			 <p>This is part two in the PHP Transaction Manager Series.  You may also find the related entries in this series of interest:</p>

<ul>
<li><a href="/blog/article/making_it_transaction_anything_in_php">Part 1: Touching the Surface - Theory</a></li>
<li>Part 2: Architecture and Components</li>
</ul>

<p><em>Note: This article was written under the guise of PHP 4, which lacks a lot of object related functionality that would be beneficial to the development of the code used in these examples.</em>&#8230;</p>
		]]></description>
		<content:encoded><![CDATA[
			<p>This is part two in the PHP Transaction Manager Series.  You may also find the related entries in this series of interest:</p>

<ul>
<li><a href="/blog/article/making_it_transaction_anything_in_php">Part 1: Touching the Surface - Theory</a></li>
<li>Part 2: Architecture and Components</li>
</ul>

<p><em>Note: This article was written under the guise of PHP 4, which lacks a lot of object related functionality that would be beneficial to the development of the code used in these examples.</em></p>

<p>It's been a while since I've touched on the topic, mostly because I've been busy with work for Gaia.  However, this incubation period has let the transaction system mature, and it continues to hold out well with over 29 million completed transactions in the last 7 months.  Since its inception, it's been adjusted to support item granting, and is currently being extended to support transactions in the Gaia Marketplace / Auction House.  In the first article, I covered the surface of the transaction manager, and some of Fowler's theories which were behind it.  In order to avoid recoding large parts of the site, a lock-first mentality was chosen for how to handle keeping an account up to date.  This time, we're going to focus on all the players / classes of the transaction manager and how they work together.</p>

<p>As in most programming languages, PHP provides support for both public and private methods within a class.  In development, one of the primary objectives was to minimize the external facing interface for the end-developer, while still keeping the backend components easy for a developer to maintain.  Each component was given specific tasks, responsibilities, and a list of classes that it would couple with in order to provide functionality.</p>

<p>For a helpful guide, I strongly reccomend having the following image open in a new window:
<a href="/media/2006/10/02-transaction_architecture/banktransactionmanager.png">Transaction Overview Diagram</a></p>

<h2>Bank Transaction Manager</h2>

<p>The first component is the first of three end-developer facing classes.  The Bank Transaction Manager is responsible for creating Transaction Entries, adding Transaction Entries to its internal stack, and then processing the entry stack while reporting on the success or failure of the process.  When a Bank Transaction Manager is initialized, it creates an Account Manager object for tracking the accounts which it needs to load.  As entries are created with the <code>createEntry()</code> method, they are fed to the end developer and then added back in to the system via <code>addEntry()</code>.</p>

<p>A Transaction Entry is nothing more than a shell object, providing a clean interface for setting an object's ID, it's attribute, quantity, and other associated properties.  When <code>addentry()</code> is called, the Bank Transaction Manager uses these properties in order to decide what Account to load (via the Account Manager).  This pairing is then set aside until execution.</p>

<p>During the execution phase, the Bank Transaction Manager tells the Account Manager to initialize all relevant accounts.  It then loops through every entry/account pair and passes the entry into the account.  In processing terms, these are called <strong>posting rules</strong>.  Every posting rule has a boolean success, and the sum of all functions returning an ultimate success or failure for <code>execute()</code>.</p>

<p>If any errors are encountered, the Bank Transaction Error (a simple static class) is written to with information about the failure.</p>

<h2>Account Manager</h2>

<p>In a horizontally scaled environment, a user's inventory or a row of trading information might reside on completely separate machines.  To encapsulate the loading and saving of these various things is the reason for the Account Manager object.  Requested accounts are queued up, and then loaded via a single call to <code>loadAccounts()</code>.  Beyond simply loading accounts, the account manager should be able to</p>

<ul>
<li>handle information if the account has changed</li>
<li>Prevent data overlap by avoiding querying for duplicate data</li>
<li>provide an interface for the instantiation of new Account objects</li>
</ul>

<p>During the execution of the Bank Transaction Manager, the Account Manager is called (specifically when <code>BankTransactionManager::addEntry()</code> is used).  Accounts are queued for loading as entries are added, and are then loaded at once.  There are two ways to load the account data, one which uses blocking, and one which does not.  Even at 4.5 million registered members, the blocking method has not been an issue, and so that is the method we'll be talking about.  In an InnoDB database, a row can be locked during the select phase as part of a transaction by using the following syntax:</p>

<textarea name="code" class="sql">SELECT 'columns' FROM 'table' WHERE 'criteria' FOR UPDATE;</textarea>

<p>The <code>FOR UPDATE</code> places a lock on the row, leaving your PHP script as the only script that has access until the lock expires.  This feature is only available on InnoDB however, as the MyISAM engine supports neither row locking nor transactions.</p>

<p>When asked to save, the AccountManager calls the <code>isChanged()</code> method on every account in order to verify if it has been altered.  Accounts which have been altered are then saved back to the database and the locks released.</p>

<h2>Transaction Entry</h2>

<p>There's not much to say about the TransactionEntry object.  As a shell, all it contains is a data payload. It's information consists of: "how many", "of what", "with what serial", and "adding or subtracting".  To help simplify the development end, the Entry object is extended to support Game items, Regular Items, Gold, and Gift Credits.  During execution, these small instruction sets are passed to the Account object.</p>

<h2>Account</h2>

<p>Defined as the authoritative source regarding all data coming in and going out, these objects are modeled in spirit after the VO J2EE pattern.  They exist to hold an account's data, and are decorated with methods to support the changing of that data.  When the Account Manager calls <code>loadAccounts()</code>, every queued account object is asked for its database information and required fields.  The sum of this data is aggregated, and passed into the <code>importData($fieldName, $data)</code> function.  When the Bank Transaction Manager executes, it then takes every Transaction Entry object, and passes it directly into <code>postEntry($t)</code>.  It is at this point that the heavy lifting is actually done.</p>

<p>Every account maintains a ruleset for how its data is to be altered, known as "posting rules".  These rules are very strict, and breaking them should cause the entire transaction to fail for the user and return an error.  The most common example of failure is if the posting rule contains an item type that the account does not support, such as posting gold information to an inventory account.  With a single public interface, the logic of altering the account information is also internalized, protecting it from the outside world.  Upon altering the account, <code>postEntry()</code> will return either TRUE or FALSE, which will be evaluated by the Bank Transaction Manager object.</p>

<p>Adding new accounts or extending existing accounts to add functionality is very easy.  The methods exposed publicly are small, specifically <code>getDaoName()</code> and <code>getDaoFields()</code> for Gaia's database support, <code>importData()</code> for loading, <code>exportAccount()</code> for saving, <code>isChanged()</code> for the Account Manager's save required check, and <code>postEntry()</code> for altering the account's data.</p>

<h2>Code in Practice (End Developer Side)</h2>

<p>For as complicated as this all seems, the code which ends up facing the developer is only the Bank Transaction Manager and Transaction Entry's public methods.  The Account Manager and Account exist outside of the end-developer's scope, unless they are building in support for additional account types.</p>

<textarea name="code" class="php">$btm = new BankTransactionManager($transaction);

// create entry (Account, Entry Type)
$e = $btm-&gt;createEntry(&quot;Gold.Gold&quot;);
$e-&gt;setUserId($user_id);
$e-&gt;addGold($gold_amount);
$btm-&gt;addEntry($e);

$e = $btm-&gt;createEntry(&quot;ServerGold.Gold&quot;);
$e-&gt;setUserId(ENTITY_SERVER);
$e-&gt;subtractGold($gold_amount);
$btm-&gt;addEntry($e);

try {
    $btm-&gt;execute();
}
catch (Exception $e) {
    throw $e;
}</textarea>

		<img src="http://feeds.feedburner.com/~r/felocity/~4/130324697" height="1" width="1"/>]]></content:encoded>
		<dc:subject>Programming</dc:subject>
		<dc:date>2006-10-03T06:59:01-08:00</dc:date>
		<dc:creator>Jakob Heuser</dc:creator>
	 <feedburner:origLink>http://www.felocity.org/blog/article/php_transaction_manager_architecture/</feedburner:origLink></item>

	 
	 </channel>
</rss>
