<?xml version="1.0" encoding="UTF-8"?>
<feed>
   <title>Fleegix.org</title>
   <link>http://fleegix.org/</link>
          <article>           <body>
               <![CDATA[In the most recent round of updates, [Larz Conwell](https://twitter.com/larzconwell) has done a shit-ton of amazing work on templates: making the templating system play nicely with various formats: EJS, Mustache, and Jade. It can now happily figure out what sort of template from the file-extension, and you can even mix and match different formats together in layouts/partials.

He's also implemented Rails-like view-helpers like `urlFor` and `linkTo`, making your views simpler and more DRY.

Last but not least, he's vastly improved the generators to support full scaffold-generation, not just minimal resources.


### What else is changing?

There's a lot of work happening on Geddy -- mostly breaking the project apart to make it more modular.

### Utilities

The large set of utility functions (most of which originated in the now-ancient [Fleegix.js](https://github.com/mde/fleegix-js-javascript-toolkit) library) have been pulled out into their own library, [Utilities](https://github.com/mde/utilities).

This classic collection of JavaScript utilities is of course [available on NPM](https://npmjs.org/package/utilities). String-manipulation, datetime stuff, mixin, filesystem utilities -- there's a ton of useful shit in there.

### Model

Even more importantly, the Geddy model code now resides in a separate project, simply called [Model](https://github.com/mde/model), which is a general-purpose, datastore-agnostic ORM library in JavaScript.

I built Postgres support first, but back-porting Geddy's existing support for MongoDB, and building a Riak adapter, are next in line. Model is also [installable via NPM](https://npmjs.org/package/model), but documentation hasn't moved over from the Geddy project, so it's still rather DIY.

### When is this happening?

The libraries are usable as-is, but the Geddy work for this lives in a branch -- but as you see, it's solid enough to build real applications with, so it will be landing soon.
I'm pretty excited to have a solid framework for building Web apps like this in JavaScript.]]>
           </body>
           <title>
               <![CDATA[Major Geddy updates]]>
           </title>
           <publishedAt>2012-08-23T19:10:09.967Z</publishedAt>
           <permalink>http://fleegix.org/2012-08-23-major-geddy-updates</permalink>
</article>
       <article>           <body>
               <![CDATA[It's taken some time, a lot of late-night hacking, and tons of work by contributors like [Daniel Erickson](https://twitter.com/techwraith) and [Larz Conwell](https://twitter.com/larzconwell), but the [Geddy Web framework](http://geddyjs.org/) is starting to grow up and become pretty fucking solid.

It's finally far enough along I can replace my old blog application, which has been running on the Merb-based [PmpknPi blog-engine](https://github.com/sintaxi/pmpknpi) for ages (anybody remember Merb?), with a very simple Geddy app. I've actually waited a really long time for this.]]>
           </body>
           <title>
               <![CDATA[Fleegix on Geddy]]>
           </title>
           <publishedAt>2012-08-23T02:59:00.284Z</publishedAt>
           <permalink>http://fleegix.org/2012-08-22-fleegix-on-geddy</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>At a recent meetup, a guy in the community (a guy whom I generally have a lot of respect for) said one of the stupidest things I've heard in a long time (and that's saying something, given the silly shit I hear coming out of my own mouth day to day).</p>

<p>We were talking about an open-source project I started working on quite a while back, and why development on it kind of stalled for a while. He was totally convinced that the reason it had stalled was because I'm an older guy with a family. I told him no, it was because my work on <a href="http://www.yammer.com/">Yammer</a> takes up most of my time. We're <a href="http://techcrunch.com/2012/02/02/yammer-time-2011everything-tripled/">pretty busy these days at Yammer</a>.</p>

<p>Now, this guy is at a startup, so I would assume he'd totally get this, but bizarrely, he acted as if he hadn't even heard me (we were at a noisy bar; I guess it's possible somehow he actually didn't hear me), and continued to hold forth, saying, with a big grin, "that's why I'd never hire an older guy with a family."</p>

<p>Yeah, sure, I'm rolling my eyes at this because I'm one of those older dudes with a family. But you can see this same silliness in other places: "I'd never hire a woman, because she might get pregnant and have to quit." "I'd never hire a person without a comp-sci degree from an elite univerity and a high GPA, because we want smart people." "I'd never hire a person from Uzbekistan, because fluctuations in their currency's exchange-rate might distract them from their work." "I'd never hire a person who's lactose-intolerant, because we'd have to keep that special milk in the office." None of these make any fucking sense either.</p>

<p>As wrong as it is, I guess I can understand where the idea comes from -- it seems obvious that younger folks have a lot more time to hack. That is, unless they're spending their free time rock-climbing, or snow-boarding, hanging out at bars, or even, say, recovering from hangovers (okay, I still do this last one from time to time, too).</p>

<p>A previous startup where I worked was populated overwhelmingly with younger dudes who prided themselves on their ability to code for days and days at a time. They produced prodigious amounts of code -- and it was some of the most appallingly bad code I've ever seen. Piles and piles of it.</p>

<p>It's possible that older guys with families work fewer hours (although that hasn't been my experience in startups so far), but it's also highly likely that with their experience they spend more time writing the <em>right</em> code. Just sayin'.</p>]]>
           </body>
           <title>
               <![CDATA[Older programmers with families considered harmful?]]>
           </title>
           <publishedAt>2012-02-03T11:24:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2012-02-03-older-programmers-with-families-considered-harmful</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Some of the work I'm doing at <a href="http://yammer.com/">Yammer</a> involves writing JavaScript code that runs in different environments. We're using <a href="http://github.com/mde/geddy/tree/master/geddy-model/">geddy-model</a> code in the browser, as well as with <a href="http://github.com/cowboyd/therubyracer">TheRubyRacer</a> (which embeds the V8 JavaScript interpreter in a Ruby process).</p>

<p>This code is part of the <a href="http://geddyjs.org/">Geddy</a> web framework I have been building for Node.js -- so this means three different environments, and and four different JavaScript interpreters, that this code has to work within.</p>

<h3>Multi-environment testing? Dual-sided? X-env?</h3>

<p>I've been talking to people about ways to solve this -- in particular, <a href="http://anders.conbere.org/">Anders Conbere</a>, who is working with similar issues at his job with <a href="http://estately.com">Estately</a>.</p>

<p>Testing multi-environment JavaScript code is an annoying problem. I looked around, I really didn't find any good solutions.</p>

<p>(I also didn't find anything nice and snappy to call JS code that has to run on both client and server. What's the "Ajax" of that? "Dual-sided"? "Multi-environment"? "JS-everywhere"?)</p>

<h3>Meet Logan</h3>

<p>I sat down to see what would be required to run the same tests in all these different environments, and it turned out to be pretty reasonable to build something that can run both brower- and server-side tests (thanks, Node.js!).</p>

<p>Despite having built <a href="http://wiki.github.com/windmill/windmill/javascript-tests">Windmill's complex JavaScript API</a> (or perhaps because of it), I've come around to <a href="http://www.mikealrogers.com/">Mikeal's</a> way of thinking on testing: I want something minimal, without a lot of frameworky baggage -- something that just sets up some conditions and does some asserts.</p>

<p>What I've ended up with is <a href="http://github.com/mde/logan">Logan</a>, a very small test runner that lets you run your tests in browsers, in Node.js, and in embedded V8 with TheRubyRacer.</p>

<p>The name is probably kind of obvious to anybody who's familiar with old sci-fi movies -- <a href="http://en.wikipedia.org/wiki/Logan's_Run_(film">Logan is a runner</a>), of course.</p>

<p>Logan uses a <a href="http://github.com/mde/logan/blob/master/lib/deps/assert.js">version of Node's assert module that Anders patched</a> to remove the V8-specific code. I would love to see these changes pushed upstream to Node, so this fork doesn't have to persist (assuming there's a minimal performance impact).</p>

<p>Logan requires Node.js, and of course if you want to test out tests in TheRubyRacer, you need to have it installed.</p>

<h3>Sharing code between sides</h3>

<p>For Logan's testing purposes, "server-side" means in Node.js, which uses CommonJS modules. "Client-side" includes the browsers, and TheRubyRacer, where there is no facility for loading code modules from within the runtime. Logan uses plain requires for the server-side, and eval/script-append in the clients.</p>

<p>I should take a second here to call out very specifically one of the requirements is synchronous loading of dependencies. (This is why I went the route of source-code transformation.)</p>

<p>Once you get past some initial hackery, it's not that bad loading code in these different enviroments. (After you've done enough client-side JavaScript, I suspect your threshold for hackery gets a little higher.)</p>

<p>To make this stuff work, you do have to follow some specific rules in both app-code, and testing code. (The constraints for the app code are needed if you plan to run your code on both client and server at all, not specifically for running Logan tests.)</p>

<h4>1. Use namespaces in your modules</h4>

<p>Use a namespace object inside the module file -- you won't have module scope when you load it in the browser. Name it the same name as the variable you'll be setting it to when you load it via CommonJS <code>require</code></pre>.</p>

<h4>2. Check for the need to export</h4>

<p>Only export your namespace in the CommonJS environment.</p>

<p>For example, in the module file, foo.js:</p>

<pre><code>if (typeof foo != 'undefined') { foo = {}; }

foo.bar = new function () {
  this.a = 1;
  this.b = function () {}; 
}();

if (typeof module != 'undefined') { module.exports = foo.bar; }
</code></pre></pre>

<p>Or, if you are exporting a constructor:</p>

<pre><code>if (typeof foo != 'undefined') { foo = {}; }

foo.Baz = function () {
  this.a = 2;
  this.b = []; 
};  

if (typeof exports != 'undefined') { exports.Baz = foo.Baz; }
</code></pre></pre>

<h4>3. Set require result to namespace name</h4>

<p>Use the same name as the namespace you created in the module for the variable name of the <code>require</code></pre> result.</p>

<h4>4. Create top-level namespaces non-destructively.</h4>

<p>In your tests, if you're creating top-level namespaces to hang your required objects on, use something to create them that checks for their existence before creating.</p>

<p>Logan includes a utility function, <code>logan.namespace</code></pre>, to help with this. In your own app's code, you'll either have to use a utility function for doing this, or simply check with a <code>typeof</code></pre> check for <code>undefined</code></pre>.</p>

<p>Here's how to load and use the previous two examples:</p>

<pre><code>logan.namespace('foo');
foo.bar = require('./path/to/foo');
foo.Bar = require('./path/to/bar').Bar;

var fooTests = new function () {
  this.testFooBarAIsTruthy = function () {
    assert.ok(foo.bar.a);
  };

  this.testFooBazAIsNumber = function () {
    var barInstance = new foo.Bar();
    assert.equal(typeof barInstance.a, 'number');
  };

}();

logan.run(fooTests);
</code></pre></pre>

<h3>Details</h3>

<p>The reason for these special requirements is the difference between the way that code loads on the client and the way it loads via CommonJS.</p>

<p>In the client environment (including TheRubyRacer), there is no module-level scope, and the mechanism for loading code doesn't return any value, so namespace creation has to happen inside the module file, and has to be careful not to rewrite anything other modules might have done.</p>

<p>Logan makes this work with CommonJS <code>require</code></pre> syntax in your tests by doing source-code transformation -- it uses the require statements to know what code to load, and rewrites the statements so they don't stomp on the results of the previous <code>eval</code></pre> operation.</p>

<p>If you're at all interested in the icky rewriting tricks necessary, have a look at the source for <a href="http://github.com/mde/logan/blob/master/lib/browser/runner.js">the browser runner</a>.</p>

<p>The process for running tests in TheRubyRacer is pretty weird too -- Node shells out to a Ruby script that then turns right back around and embeds V8. It's a crazy world we're living in.</p>

<h3>What's next</h3>

<p>Logan is very new. I'm sure there are better ways to deal with the problems of X-env testing. (How about that? Yeah, "X-env"? It has the letter "X" in it like Ajax, right?) At least I <em>hope</em> there are better ways. I'm very interested in getting feedback on how to make improvements.</p>]]>
           </body>
           <title>
               <![CDATA[Logan, client- and server-side JavaScript test runner]]>
           </title>
           <publishedAt>2010-07-17T22:28:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2010-07-17-logan-client-and-server-side-javascript-test-runner</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>The last couple of weeks have been a blast.</p>

<p>I've been settling into my new job at Yammer, getting to know the guys on the team, and enjoying the insanely delicious food. Yes, we have a chef that comes in; it's pretty ridiculous.</p>

<p>By happy accident, my team at Yammer is using the work I've done with <a href="http://github.com/mde/geddy">Geddy</a> on models and validations -- but in the browser.</p>

<p>It's kind of mind-bending to see code written for Node.js running in IE6, but that's a real-world example of the pure awesome we get with server-side JavaScript. No more writing the exact same input-validation in two different languages.</p>

<p>Geddy has an easy, intuitive way of defining models, with
a full-featured set of data validations. The syntax is very
similar to models in Ruby's ActiveRecord or DataMapper, or Python's SQLAlchemy.</p>

<p>As I mentioned, the model module works great both in Node, and in the browser, so it's very easy to share model and input validation code in your app between client and server.</p>

<p>Here is an example of a model with some validations:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">var</span> User = <span class="r">function</span> () {
  <span class="pc">this</span>.property(<span class="s"><span class="dl">'</span><span class="k">login</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">String</span><span class="dl">'</span></span>, {required: <span class="pc">true</span>});
  <span class="pc">this</span>.property(<span class="s"><span class="dl">'</span><span class="k">password</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">String</span><span class="dl">'</span></span>, {required: <span class="pc">true</span>});
  <span class="pc">this</span>.property(<span class="s"><span class="dl">'</span><span class="k">lastName</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">String</span><span class="dl">'</span></span>);
  <span class="pc">this</span>.property(<span class="s"><span class="dl">'</span><span class="k">firstName</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">String</span><span class="dl">'</span></span>);

  <span class="pc">this</span>.validatesPresent(<span class="s"><span class="dl">'</span><span class="k">login</span><span class="dl">'</span></span>);
  <span class="pc">this</span>.validatesFormat(<span class="s"><span class="dl">'</span><span class="k">login</span><span class="dl">'</span></span>, <span class="rx"><span class="dl">/</span><span class="k">[a-z]+</span><span class="dl">/</span></span>,
      {message: <span class="s"><span class="dl">'</span><span class="k">Subdivisions!</span><span class="dl">'</span></span>});
  <span class="pc">this</span>.validatesLength(<span class="s"><span class="dl">'</span><span class="k">login</span><span class="dl">'</span></span>, {min: <span class="i">3</span>});
  <span class="pc">this</span>.validatesConfirmed(<span class="s"><span class="dl">'</span><span class="k">password</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">confirmPassword</span><span class="dl">'</span></span>);
  <span class="pc">this</span>.validatesWithFunction(<span class="s"><span class="dl">'</span><span class="k">password</span><span class="dl">'</span></span>, <span class="r">function</span> (s) { 
      <span class="c">// Something that returns true or false</span>
      <span class="r">return</span> s.length &gt; <span class="i">0</span>;
  });
  <span class="c">// Can define methods for instances like this</span>
    <span class="pc">this</span>.someMethod = <span class="r">function</span> () {
      <span class="c">// Do some stuff</span>
    };
};

<span class="c">// Can also define them on the prototype</span>
User.prototype.someOtherMethod = <span class="r">function</span> () {
  <span class="c">// Do some other stuff</span>
};

<span class="c">// Server-side, commonjs</span>
exports.User = User;
<span class="c">// Client-side</span>
<span class="c">// model.registerModel('User');</span></pre></div>
</div>

<p>Creating an instance of one of these models is easy:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">var</span> params = {
  login: <span class="s"><span class="dl">'</span><span class="k">alex</span><span class="dl">'</span></span>,
  password: <span class="s"><span class="dl">'</span><span class="k">lerxst</span><span class="dl">'</span></span>,
  lastName: <span class="s"><span class="dl">'</span><span class="k">Lifeson</span><span class="dl">'</span></span>,
  firstName: <span class="s"><span class="dl">'</span><span class="k">Alex</span><span class="dl">'</span></span>
};
<span class="r">var</span> user = User.create(params);</pre></div>
</div>

<p>Data-validation happens on the call to <code>create</code></pre>, and any
validation errors show up inside an <code>errors</code></pre> property on
the instance, keyed by field name. Instances have a <code>valid</code></pre>
method that returns a Boolean indicating whether the instance
is valid.</p>

<div class="CodeRay">
  <div class="code"><pre><span class="c">// Leaving out the required password field</span>
<span class="r">var</span> params = {
  login: <span class="s"><span class="dl">'</span><span class="k">alex</span><span class="dl">'</span></span>,
};
<span class="r">var</span> user = User.create(params);

<span class="c">// Prints 'false'</span>
sys.puts(user.valid());
<span class="c">// Prints 'Field &quot;password&quot; is required'</span>
sys.puts(user.errors.password);</pre></div>
</div>

<p>I've been writing a bunch of <a href="http://github.com/mde/geddy/tree/master/geddy-model/test/">tests</a> so you can see some other examples.</p>

<p>Really cool seeing code that runs equally well on the server and in the browser. A credible server-side JavaScript plaform like Node really opens up a ton of new possibilities. Looking forward to seeing where it all goes.</p>]]>
           </body>
           <title>
               <![CDATA[Geddy models/validations for Node.js]]>
           </title>
           <publishedAt>2010-04-26T22:53:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2010-04-26-geddy-models-validations-for-node-js</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I've just come back from a meeting at the offices of my new employer, <a href="http://yammer.com/">Yammer, Inc</a>. I've accepted a position there as Senior Front-End Engineer, doing development work primarily in JavaScript and Ruby.</p>

<p>I start next week, after enjoying a little family time this week -- coincidentally it's spring break for my boys.</p>

<p>For those who don't know, Yammer is a <a href="http://en.wikipedia.org/wiki/Microblogging">microblogging</a> service for the enterprise. Think Twitter, or Facebook's News Feed, but for use in businesses.</p>

<p>Yammer is an excellent fit -- I've been a heavy user of microblogging and 'activity streams' since the fairly early days of Twitter.</p>

<p>It's easy to see the impact this new medium of communication has had on people's personal lives. I'm looking forward to helping invent how it impacts people in the the workplace.</p>

<p>The Yammer office is at Townsend and 5th in downtown San Franciso, very near South Park and the baseball stadium, so my commute remains a breezy 15-minutes up 280.</p>

<p>If you happen to find yourself in that part of town, hit me up -- I'd love to go have lunch.</p>]]>
           </body>
           <title>
               <![CDATA[What's next is Yammer]]>
           </title>
           <publishedAt>2010-04-05T17:16:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2010-04-05-what-s-next-is-yammer</permalink>
</article>
       <article>           <body>
               <![CDATA[<p><a href="http://github.com/mde/geddy">Geddy</a> is a small Web-app development framework for Node.js. It uses a router syntax similar to Rails or Merb, and now has tools for quickly creating RESTful, resource-based routes as well.</p>

<h2>Building and installing Geddy</h2>

<p>Prerequisites: An up-to-date version of Node.js. I'm developing Geddy on Linux (and I'm lazy), so I'm not sure yet what adjustments might be needed for it to work smoothly on OS X. I hope one of you Mac guys can tell me what's needed.</p>

<p>Get Geddy from GitHub and install:</p>

<div class="CodeRay">
  <div class="code"><pre>git clone git://github.com/mde/geddy.git
cd geddy
make &amp;&amp; sudo make install</pre></div>
</div>

<p>There's currently no configure step, because the installation is really just packaging stuff up, and a little file-copying. The installation sticks Geddy into .node_libraries/ in your home directory.</p>

<h2>Creating a Geddy app</h2>

<p>Geddy comes with a utility called <code>geddy-gen</code></pre> you can use to create an app:</p>

<div class="CodeRay">
  <div class="code"><pre>mde@localhost:~/work$ geddy-gen app bytor
Created app bytor.
mde@localhost:~/work$ cd bytor
mde@localhost:~/work/bytor$ geddy
Server running at http://127.0.0.1:8000/</pre></div>
</div>

<p>Go to http://localhost:8000/, and you should see:</p>

<p><strong>Attention all planets of the Solar Federation</strong></p>

<p>Pretty simple.</p>

<p>What's in a Geddy app? Well, geddy-gen starts you off with a simple app stub. The directory contents look like this:</p>

<div class="CodeRay">
  <div class="code"><pre>mde@localhost:~/work$ find bytor
bytor
bytor/config
bytor/config/router.js
bytor/app
bytor/app/controllers
bytor/app/controllers/main.js
bytor/public</pre></div>
</div>

<p>There's just a single, simple default route in router.js:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">var</span> Router = require(<span class="s"><span class="dl">'</span><span class="k">geddy/lib/router</span><span class="dl">'</span></span>).Router;

router = <span class="r">new</span> Router();
router.match(<span class="s"><span class="dl">'</span><span class="k">/</span><span class="dl">'</span></span>).to({controller: <span class="s"><span class="dl">'</span><span class="k">Main</span><span class="dl">'</span></span>, action: <span class="s"><span class="dl">'</span><span class="k">index</span><span class="dl">'</span></span>});

exports.router = router;</pre></div>
</div>

<p>This has the the / path handled by the index action on the Main controller.</p>

<h2>Adding resources</h2>

<p>Change directories into your new app directory, and use <code>geddy-gen resource</code></pre> to create one:</p>

<div class="CodeRay">
  <div class="code"><pre>mde@localhost:~/work/bytor$ geddy-gen resource snow_dogs
[ADDED] ./app/controllers/snow_dogs.js
resources snow_dogs route added to ./config/router.js</pre></div>
</div>

<p>Restart Geddy, and you'll see the new route working. Hit your new route -- for example, http://localhost:8000/snow_dogs.json, and you should see something like this:</p>

<p><strong>{"method":"index","params":{"extension":"json"}}</strong></p>

<p>Depending on how your browser is set up to deal with the JSON MIME type, it may want to open the response in a separate application.</p>

<h2>Resource controllers</h2>

<p>Take a look at the new file created, app/controllers/snow_dogs.js to see what actions a resource-based controller has. The actions are methods called on the controller, and get passed a copy of the parsed parameters from the URL and query string.</p>

<p>Okay, so REST isn't quite the same as CRUD, but Geddy's resource-based routes do take the expedient course of creating url/request-method mappings for easy CRUD operations like this:</p>

<p>GET <em>/snow_dogs</em><br/>
(SnowDogs controller, index action)</p>

<p>GET <em>/snow_dogs/add</em><br/>
(SnowDogs controller, add action, for any new-resource template -- "new" is not usable as a JavaScript action name)</p>

<p>POST <em>/snow_dogs</em><br/>
(SnowDogs controller, create action)</p>

<p>GET <em>/snow_dogs/:id</em><br/>
(SnowDogs controller, show action)</p>

<p>PUT <em>/snow_dogs/:id</em><br/>
(SnowDogs controller, update action)</p>

<p>DELETE <em>/snow_dogs/:id</em><br/>
(SnowDogs controller, remove action)</p>

<h2>Content-negotiation</h2>

<p>Geddy has some built-in ability to perform content-negotiation based on the abilities of the client, and the requested filename-extension. Right now, this feature is very bare-bones, supporting only JSON and plaintext, but can be easily extended to support XML, Atompub, or whatever.</p>

<p>If you have a JSON-serializable JavaScript object you want to return in JSON format, all you have to do is set up a resource with <code>geddy-gen resource</code></pre>, and in the appropriate controller action, pass your JavaScript object to the respond method.</p>

<p>Something like this:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="pc">this</span>.respondsWith = [<span class="s"><span class="dl">'</span><span class="k">text</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">json</span><span class="dl">'</span></span>];

<span class="pc">this</span>.show = <span class="r">function</span> (params) {
  <span class="c">// (Fetch some item by params.id)</span>
  item = {foo: <span class="s"><span class="dl">'</span><span class="k">FOO</span><span class="dl">'</span></span>, bar: <span class="i">1</span>, baz: <span class="pc">false</span>};
  <span class="pc">this</span>.respond(item);
};</pre></div>
</div>

<p>Geddy will automatically serialize <code>item</code></pre> to JSON, and set the content-type appropriately -- assuming the client can accept JSON.</p>

<p>Eventually it should be possible to register handlers for new content-types on a per-controller, or per-model basis. (Doing this by way of defining a 'to_[format]' method on the objects to be returned isn't a workable solution in JavaScript, when you're likely to be returning built-in types.)</p>

<p>If you want to use a specific format, you can pass it as the second argument to the <code>respond</code></pre> call -- even if it's not one of the listed formats in <code>respondsWith</code></pre>. </p>

<p>Perhaps something like this:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="pc">this</span>.show = <span class="r">function</span> (params) {
  <span class="c">// (Fetch some item by params.id)</span>
  item = {foo: <span class="s"><span class="dl">'</span><span class="k">FOO</span><span class="dl">'</span></span>, bar: <span class="i">1</span>, baz: <span class="pc">false</span>};

  <span class="c">// Serve up some html</span>
  <span class="r">if</span> (params.extension == <span class="s"><span class="dl">'</span><span class="k">html</span><span class="dl">'</span></span>) {
    <span class="r">var</span> html = <span class="s"><span class="dl">'</span><span class="dl">'</span></span>;
    html += <span class="s"><span class="dl">'</span><span class="k">&lt;html&gt;&lt;body&gt;</span><span class="dl">'</span></span>;
    html += <span class="s"><span class="dl">'</span><span class="k">&lt;h3&gt;</span><span class="dl">'</span></span> + item.foo + <span class="s"><span class="dl">'</span><span class="k">&lt;/h3&gt;</span><span class="dl">'</span></span>;
    html += <span class="s"><span class="dl">'</span><span class="k">&lt;/body&gt;&lt;/html&gt;</span><span class="dl">'</span></span>;
    <span class="pc">this</span>.respond(html, <span class="s"><span class="dl">'</span><span class="k">html</span><span class="dl">'</span></span>);
  }
  <span class="c">// Otherwise return formatted data</span>
  <span class="r">else</span> {
    <span class="pc">this</span>.respond(item);
  }
};</pre></div>
</div>

<p>Geddy uses simple strings for the identifiers of the formats, rather than an enumeration, because it's just cleaner-looking. I prefer simply <code>'json'</code></pre> to <code>this.formats.JSON</code></pre> or something like that.</p>

<h2>What's next?</h2>

<p>Next is work on easy handling of templates. I'm not sure how far down the HAML/SASS road I want to go initially, but basic EJS, and Moustache seem like a good place to start.</p>]]>
           </body>
           <title>
               <![CDATA[REST easy with Geddy for Node.js]]>
           </title>
           <publishedAt>2010-03-25T01:20:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2010-03-25-rest-easy-with-geddy-for-node-js</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>So I've posted previously about the embarrassment of riches that we have with Node.js modules, specifically Web frameworks. </p>

<p>I count no less than 14 frameworks and micro-frameworks for building Web-apps with Node right now on the <a href="http://wiki.github.com/ry/node/modules">list of Node modules</a>.</p>

<p>I had actually hoped to use one of these to build a small Node app, but as it turns out, many of these are either half-finished, or are broken with current versions of Node. Pretty understandable, given how quickly Node is changing.</p>

<p><a href="http://github.com/visionmedia/express/tree/master">Express</a> looks good, but I'm a little more interested in something that will let me build complex apps -- and the Sinatra-style routing, with the verb and everything kind of inline there, seems a little verbose. I prefer the simpler DSL of Rails-/Merb-style routes. To me it's just more expressive, flexible, and powerful.</p>

<p>So I started building a basic router, looking at a lot of the ideas in <a href="http://github.com/obt/bomberjs">Bomber.js</a>, and remembering back on how simple and hackable the Merb framework was to use.</p>

<p>The result is Geddy. It's a small Web-app development framework that's still very embryonic -- but it does routing and invoking controller actions, and serves static files. I'm having a blast hacking on it. It's crazy fun doing all this server-side code in JavaScript.</p>

<p>Of course, it's named in honor of <a href="http://en.wikipedia.org/wiki/Geddy_Lee">Geddy Lee</a>, the bassist for Rush.</p>

<h2>Routing</h2>

<p>Routes in Geddy look like this:</p>

<div class="CodeRay">
  <div class="code"><pre>r = <span class="r">new</span> Router();
r.match(<span class="s"><span class="dl">'</span><span class="k">/</span><span class="dl">'</span></span>).to({controller: <span class="s"><span class="dl">'</span><span class="k">Main</span><span class="dl">'</span></span>, action: <span class="s"><span class="dl">'</span><span class="k">index</span><span class="dl">'</span></span>}).name(<span class="s"><span class="dl">'</span><span class="k">main</span><span class="dl">'</span></span>);
r.match(<span class="s"><span class="dl">'</span><span class="k">/users/:userid/lerxstizer/:lerxstid</span><span class="dl">'</span></span>).to(
  {controller: <span class="s"><span class="dl">'</span><span class="k">Users</span><span class="dl">'</span></span>, action: <span class="s"><span class="dl">'</span><span class="k">lerxstizer</span><span class="dl">'</span></span>});</pre></div>
</div>

<p>This should look pretty familiar to anybody who's used Merb or Rails. The controller here is really just an execution context for the action, which is really just a handler method.</p>

<p>The advantage of thinking of these as 'controller' and 'action' is that it allows the execution context of the handler method to inherit a bunch of helpful methods from a base Controller.</p>

<p>It also leverages people's understanding of MVC so the on-ramp to building something is minimal.</p>

<h2>Controllers and actions</h2>

<p>On startup, Geddy scans the app/controllers directory for JavaScript files, and loads them as available controllers.</p>

<p>A sample controller file looks like this (in file app/controllers/users.js):</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">var</span> Users = <span class="r">function</span> () {
  <span class="pc">this</span>.lerxstizer = <span class="r">function</span> (params) {
    <span class="c">// params should have userid, lerxstid, and any query-string params</span>
    <span class="pc">this</span>.render(JSON.stringify(params));
  };
};

exports.Users = Users;</pre></div>
</div>

<p>The controllers are all required and instantiated based on convention, but I'm not going all meshugah with the Railsy pluralization rules.</p>

<p>The controller files should be all lowercase names, with underscores separating words. The constructor function in the file should be a camel-cased, initial-capital-letter version of the same name.</p>

<p>Some examples:</p>

<table style="width: 100%; border-collapse: collapse;">

<tr>
<td style="padding: 0.6em; border: 1px solid #aaa;">
<b>File</b>
</td>
<td style="padding: 0.6em; border: 1px solid #aaa;">
<b>Constructor</b>
</td>
</tr>

<tr>
<td style="padding: 0.6em; border: 1px solid #aaa;">
app/controllers/snow_dogs.js
</td>
<td style="padding: 0.6em; border: 1px solid #aaa;">
SnowDogs
</td>
</tr>

<tr>
<td style="padding: 0.6em; border: 1px solid #aaa;">
app/controllers/priests_of_syrinx.js
</td>
<td style="padding: 0.6em; border: 1px solid #aaa;">
PriestsOfSyrinx
</td>
</tr>

</table>

<p>The action is a method then called on the controller instance, and passed a params object that contains any params pulled off by matching the pattern in the router -- and any query-string params.</p>

<p>So for example, in the case of the 'lerxstizer' example above, if you hit the following URL:</p>

<p><code>/users/alex/lerxstizer/2112?code=YYZ</code></pre></p>

<p>The params object will look like this:</p>

<div class="CodeRay">
  <div class="code"><pre>{
  userid: <span class="s"><span class="dl">'</span><span class="k">alex</span><span class="dl">'</span></span>,
  lerxstid: <span class="s"><span class="dl">'</span><span class="k">2112</span><span class="dl">'</span></span>,
  code: <span class="s"><span class="dl">'</span><span class="k">YYZ</span><span class="dl">'</span></span>
}</pre></div>
</div>

<h2>Static files</h2>

<p>It's impossible to develop a Web application without serving the static assets needed. I took a look at how <a href="http://github.com/felixge/node-paperboy">Paperboy</a> and other frameworks did it, and added static-file support for Geddy.</p>

<p>In development-mode, if an URL matches no routes, Geddy will serve up matching filenames in the public/ directory rather than responding with a 404. Obviously this directory path needs to be configurable at some point.</p>

<h2>Stuff to do</h2>

<p>There's a long list of stuff to hack in:</p>

<ul>
<li>Resource-based routes</li>
<li>Content negotiation</li>
<li>Templating support</li>
<li>Better error handling</li>
<li>Controller-generator script</li>
<li>Kiwi package</li>
</ul>

<p>I also need to separate out the framework code from what will eventually be generated app code. Lots of stuff to work on, and hopefully lots of opportunity to get to know Node better.</p>]]>
           </body>
           <title>
               <![CDATA[Geddy: Web framework for Node.js]]>
           </title>
           <publishedAt>2010-03-15T22:46:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2010-03-15-geddy-web-framework-for-node-js</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Quite a <a href="http://wiki.github.com/ry/node/modules">growing list of Node.js modules and projects</a> on GitHub. It's like a Cambrian explosion of JavaScripty goodness.</p>

<p>If you're thinking of building a Webapp with Node, it's hard to know which of these embryonic frameworks to pick -- or if you should even pick one -- since the laws of competition dictate we'll end up with one or two large ones.</p>

<p>This is a problem I ran into working with Merb -- spending time working with a framework, submitting patches, fixing problems, only to see it subsumed into Rails.</p>

<p>I'll still probably pick one to work with, since it'll likely be as round as any wheel I could invent myself. I'll be following the trajectories of these frameworks with some real interest.</p>]]>
           </body>
           <title>
               <![CDATA[Node.js frameworks]]>
           </title>
           <publishedAt>2010-03-08T12:57:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2010-03-08-nodejs-frameworks</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I've been doing a <a href="http://trac.getwindmill.com/changeset/1361">bunch of stuff with AS3</a> at Slide, and as a long-time JavaScript guy, thought it might be interesting to record my impressions of the language so far. I'll do  the bad news first, so I can end on a positive note.</p>

<h2>The bad news</h2>

<h3>Type annotations</h3>

<p>Not a fan of the type annotations. I realize this was supposed to be one of the improvements to JS from ECMAScript 4, but so far there has not been a single instance where I've thought "wow, thank FSM I had that static typing to keep me safe."</p>

<p>I know this is jumping into the eternal static/dynamic typing debate, and I skew entirely toward the dynamic. But the reality is that I've met multiple people who've moved from using say, Java, to Ruby or JS, and they always talk about how painful it is to go back to Java. The awful verbosity is one of the reasons.</p>

<p>I see stuff like this in AS3:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">var</span> mySprite:Sprite = <span class="r">new</span> Sprite();</pre></div>
</div>

<p>This just seems silly.</p>

<p>It's also worth noting that with typed functions you can't have multiple return types from a function now, either -- for example, returning a string on success, and null on failure. (Okay, you could just type it as Object, but that seems pretty pointless.)</p>

<div class="CodeRay">
  <div class="code"><pre><span class="c">// Hello, pretty much everything is an Object</span>
<span class="c">// Why am I typing this at all?</span>
public <span class="r">function</span> foo():Object {
  <span class="c">// I'd kinda like to return different stuff here</span>
}</pre></div>
</div>

<p>And now I have to think about two different types for unassigned variables -- one for typed ones (<code>null</code></pre>) and one for untyped ones using the asterisk annotation (<code>undefined</code></pre>, like old-fashioned JS).</p>

<div class="CodeRay">
  <div class="code"><pre><span class="c">// This has a value of null</span>
<span class="r">var</span> foo:Event;
<span class="c">// This has a value of undefined</span>
<span class="r">var</span> bar:*;</pre></div>
</div>

<p>Now, there may be benefits to it that are a little bit invisible to me in day-to-day dev, like performance. But with the huge advancements in JS interpreters like the ones we're seeing in TraceMonkey, V8, and SquirrelFish, I'm a lot more dubious about the cost-benefit offered by the static typing and a compile step.</p>

<h3>Access modifiers</h3>

<p>Seeing all this public/prviate stuff everywhere makes me feel like I'm using Java. Maybe that's the whole idea; I don't know.</p>

<p>At one point I was reading documentation on the Adobe site, and it took me about 10 seconds to realize that a large chunk of code I was looking at <em>actually was</em> Java, not AS3.</p>

<p>Using enclosing scope seems mostly fine for private vars in JS. I guess the implicit binding of all the local vars to <code>this</code></pre> in instances in AS3 makes that impossible, but I get the feeling that some guys really like all the delicious explicitness they get from having to pedantically declare all this stuff.</p>

<p>For me, it's mostly just more crap to have to type, and more noise to filter out when I'm trying to read code.</p>

<h3>Closed classes</h3>

<p>Again, this is supposed to be a feature. But overriding specific behavior in a class (in say, for example, testing, which is what I'm working on) requires endless subclassing, and having to think about inheritance-chain specificity way too much.</p>

<p>The most annoying example of this so far was some code that needed to accept various types of Events, but some of the containing code might call methods on a specific subclass. The compiler really doesn't like that.</p>

<p>The only way I can see to handle that is to use the "any type" asterisk for the annotation for that param, which kind of raises the question of "this static-typing stuff, it's good for exactly what again?"</p>

<h3>Subclass 'super' invocation isn't really a function call</h3>

<p>The correlary to this endless subclassing-annoyance is that I can't call a subclass's constructor method with Function.apply, and just pass it the same arguments as the constructor. There are couple of old mailing list threads from back in 2007, one <a href="http://www.nabble.com/forum/ViewPost.jtp?post=14421842&amp;framed=y">here</a> and the other <a href="https://mail.mozilla.org/pipermail/es-discuss/2007-June/004269.html">here</a> that talk about this.</p>

<p>Even after reading these I'm still don't get the rationale for this is -- but as a mere workaday developer, I do know that forcing me to type long lists of parameters mechanically on top of the endless subclassing is horribly tedious and error-prone.</p>

<h3>Compile step</h3>

<p>Hate it.</p>

<p>I guess I'm way too ADD, or spoiled by JS Web-dev work, but I need my instant gratification. Sitting and waiting for five or six seconds for multiple interdependent SWFs to compile totally breaks my workflow.</p>

<p>I feel like I'm spending a disproportionate amount of time making the compiler happy, and less time thinking about what my program actually does.</p>

<h3>Object keys don't iterate in insertion order, WTF?</h3>

<p>Okay, so I get that this isn't in the ECMA-262 Edition 3 spec (and don't know if it was supposed to be in ECMAScript 4), but <em>every major ECMA implementation</em> iterates over an Object's keys in the insertion order.</p>

<p>I'm not sure if it's a huge perf-killer, or if they just didn't get around to making it work right, but it seems pointless to position AS3 as "JavaScript with improvements," and then screw up something so fundamental. Before you implement all the improvements, how about getting the basics right?</p>

<p>(And by 'right,' I don't mean "bare minimum correctness according to the spec," I mean "at least as good as the other implementations.")</p>

<h2>The good news</h2>

<h3>A real 'for each'</h3>

<p>It's really nice to iterate over items in an array without the tedious array-index incrementation. This is so much nicer, so much more readable:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">for</span> each (item <span class="r">in</span> someArray) { <span class="c">// Do stuff to item }</span></pre></div>
</div>

<p>Yes, I know this already exists in newer JavaScript implementations -- but we can't use it until old Internet Explorer albatross goes away.</p>

<h3>Checking for the existence of an attribute</h3>

<p>So nice to stop using the janky test for whether a property's <code>typeof</code></pre> is undefined. Now I can do:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">if</span> (<span class="s"><span class="dl">'</span><span class="k">foo</span><span class="dl">'</span></span> <span class="r">in</span> bar) { <span class="c">// Do stuff }</span></pre></div>
</div>

<p>I really like this syntax -- way more much readable.</p>

<p>If these kinds of syntactic niceties are in the more-modest ECMAScript 5, I'll definitely continue to be a happy JS programmer.</p>

<h2>In Short</h2>

<p>I guess it's pretty clear -- what I like about AS3 is its similarities to the JavaScript I know and love, and the small syntactic fixes to what have always been obvious JS warts.</p>

<p>What I don't like is all the Java-like verbosity which, thankfully seems to have died in the main JS evolutionary branch with the ill-advised ECMAScript 4 adventure.</p>]]>
           </body>
           <title>
               <![CDATA[Reflections of a JS guy on AS3]]>
           </title>
           <publishedAt>2009-08-09T19:31:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2009-08-09-reflections-of-a-js-guy-on-as3</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Okay, yeah, so I've left the blog pretty quiet the last couple of months -- it's been a busy time with lots of changes.</p>

<p>After being without a full-time gig, doing a bunch of contract work, and looking around a lot, I accepted a job offer from the nice folks at <a href="http://slide.com/">Slide</a>. The position is in their office in San Francisco, so in the last month I've moved myself and my family (and our whole houseful of crap) out to the Bay Area.</p>

<p>We're ensconced in a lovely rental in Pacifica, and loving the amazing views of the mountains, ocean ... and of course, the fog.</p>

<p>It's an interesting change going from years of working remotely from home, to working day-to-day in an office. With actual human beings in it. It's quite a change, and actually nice in a lot of ways seeing people other than my family on a regular basis, but there are downsides to the whole deal -- like, you know, having to wear pants.</p>

<p>The other big change, of course, is using Python for my server-side language of choice. I've been pretty much a Ruby guy up to this point, but Slide is a Python shop. The switch has been pretty interesting so far: I'm learning fun idioms like how to fake the ternary operator, and (of course) basic stuff like how not to screw up my indentation. I like it pretty well. Of course we're building Web apps, so there's also piles and piles of tasty JavaScript to work on.</p>

<p>Now that we're set up in our new digs (and the endless piles of boxes are mostly disposed of), and I'm managing to make major changes to code without blowing shit up, I think I'm settled in enough to begin updating here a bit more regularly.</p>

<p>Either that, or <a href="http://twitter.com/mde">microblogging</a> has killed my ability to post -- we'll see I guess.</p>]]>
           </body>
           <title>
               <![CDATA[New gig at Slide, new digs in SF, new ... Python?]]>
           </title>
           <publishedAt>2009-06-17T23:56:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2009-06-17-new-gig-at-slide-new-digs-in-sf-new-python</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>The <a href="http://www.sinatrarb.com/">Sinatra</a> Web dev framework has been around for a while, but I've recently been seeing it popping up a lot more.</p>

<p><a href="http://simonwillison.net/">Simon Willison</a>, the co-creator of the <a href="http://www.djangoproject.com/">Django</a> Python Web-dev framework, even mentioned it to me at SXSW Interactive when I buttonholed him after his panel on the <a href="http://sxsw.com/interactive/talks/panels?action=show&amp;id=IAP0901138">Changing Face of News</a>, to ask him what the Guardian is using for their API service. </p>

<p>(Sadly, he said, it's still all enterprise Java. NPR is using a mix of PHP and Java, and the New York Times runs their API service on Ruby on Rails.)</p>

<p>I suggested to Simon that Sinatra's higher profile comes from its status as the new anti-Rails, and <a href="http://brainspl.at/">Ezra Zygmuntowicz</a> said the same thing today <a href="http://twitter.com/ezmobius/status/1395468137">on Twitter</a>:</p>

<blockquote>
    <p><a href="http://twitter.com/wycats">@wycats</a> sinatra is filling the gap now that merb is an organ donor ;)</p>
</blockquote>

<p>He is of course referring to the fact that <a href="http://merbivore.com/">Merb</a>, the Ruby Web-dev framework which has proven to be a credible competitor to Rails, is now <a href="http://weblog.rubyonrails.org/2008/12/23/merb-gets-merged-into-rails-3">being merged into Rails</a> -- the result being Rails 3.</p>

<p>But Sinatra is more than that -- <a href="http://therealadam.com/">Adam Keys</a> put it well in that same back-and-forth <a href="http://twitter.com/therealadam/status/1395497769">on Twitter</a>:</p>

<blockquote>
    <p><a href="http://twitter.com/wycats">@wycats</a> I see some people taking to Sinatra now that Merb isn't the angsty choice. But mostly, its people looking to do more with less code.</p>
</blockquote>

<p>Unless you have a case of <a href="http://blog.figuringshitout.com/man-with-a-hammer-syndrome">man-with-hammer syndrome</a>, you see that no single tool is right for every job -- and Sinatra's lightweight approach (it doesn't even bill itself as a framework, just a 'DSL') looks great for simple uses where you don't need all the overhead of Rails (or even Merb).</p>

<p>I recently converted the <a href="http://js.fleegix.org/">Fleegix.js</a> project site from a Merb flat app to a <a href="http://github.com/mde/fleegix-js-javascript-toolkit/tree/5466a8986aa9fd1d6b19ebd867cf91b7f9f73078/site">gorgeously minimalist Sinatra app</a>, and found Sinatra's simple aesthetic to be just about perfect. I could also see using it for throwing up simple Web services as well (although it's hard to beat Merb's resource routes and braindead-easy display/provides content-negotiation for that).</p>

<p>My next Sinatra project will be the <a href="http://epiphanyradio.org/">EpiphanyRadio</a> site, which is definitely due for a little love. It's another simple site (currently a bunch of raw mod_ruby/eruby) which would be a lot nicer as a simple Sinatra app.</p>]]>
           </body>
           <title>
               <![CDATA[Fleegix on Sinatra]]>
           </title>
           <publishedAt>2009-03-26T23:57:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2009-03-26-fleegix-on-sinatra</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I started at Seesmic a <a href="http://www.fleegix.org/articles/2008-01-11-osaf-2-0-to-seesmic-pre-alpha">little over a year ago</a>, and it's been great helping the platform grow from a full-page Flash app prototype to an Ajaxy Web app backed by a solid REST API.</p>

<p>There is <a href="http://bible.cc/ecclesiastes/3-1.htm">a time for every purpose under the sun</a>, and now it's time for me to be moving on to other projects better aligned with my personal career goals.</p>

<p>I'm really proud of the work I did at Seesmic, and some of the early technology choices we made (<a href="http://yehudakatz.com/2008/12/23/rails-and-merb-merge/">particularly Merb</a>) have proven to be excellent bets.</p>

<p>I also feel extremely fortunate in the great people I've gotten to work with there, and owe Loic a huge debt of gratitude for that opportunity. I remain a Seesmic shareholder, and a big believer in what they're trying to do with the platform. I look forward to seeing where they take it.</p>

<p>Not sure what's ahead for me yet -- I have just started my job search, but I will be blogging (and microblogging) about the process as it unfolds.</p>]]>
           </body>
           <title>
               <![CDATA[Leaving Seesmic]]>
           </title>
           <publishedAt>2009-03-19T17:38:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2009-03-19-leaving-seesmic</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Sometime last year I found out that Apple was using the <a href="http://js.fleegix.org/plugins/date/date">fleegix.date.Date</a> plugin to build the timezone support in the MobileMe calendar, and recently had the opportunity to take a look and see what they did with it.</p>

<p>The MobileMe calendar is quite pretty, as you might expect with an app written with <a href="http://www.sproutcore.com/">SproutCore</a>. It still has some pretty rough edges (I'd say even lagging behind the UI we built for for <a href="http://chandlerproject.org/Projects/CosmoHome">Cosmo (AKA Chandler Server)</a> in a lot of areas), but is mostly speedy and pretty solid.</p>

<p>You can see from the <a href="http://www.me.com/my/calendar/en/javascript.js">core JavaScript file for the calendar</a> that Apple is indeed using fleegix.date.Date for handling timezones. Also nice to see that Apple is living up to their open-source obligations by including copyright information in their distributed source. </p>

<p>On a technical note, it's interesting to see that they're preparsing all the Oson zoneinfo data into a big JSON string and including it directly inline in the JavaScript source -- that's quite a big ol' ball of JSON data.</p>

<p>Seems pretty inefficient to me to push that out to all users (or even just all users who have timezones enabled) with no regard for how much of that data is actually ever used. But of course, MobileMe is still a relatively new product, and has a lot room for optimization.</p>

<p>I'm pretty excited to see a company like Apple building a major end-user-facing product using a <a href="http://js.fleegix.org/">Fleegix.js</a> plugin, and even more enthused about the idea that the code is getting some real large-scale usage.</p>]]>
           </body>
           <title>
               <![CDATA[Apple MobileMe using fleegix.date.Date for timezones]]>
           </title>
           <publishedAt>2009-02-09T22:13:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2009-02-09-apple-mobileme-using-fleegix-date-date-for-timezones</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>A former colleague of mine, <a href="http://www.linkedin.com/in/moisadoru">Teodor Moisa</a>, pointed out to me recently that <a href="http://js.fleegix.org/">Fleegix.js</a> is one of the libraries showing up in the scan performed by <a href="http://sourceforge.net/projects/frameworkscanne/">Framework Scanner</a>. This is a very cool utility by <a href="http://mankzblog.wordpress.com/">Mats Bryntse</a> that compares the impact on the global namespace by various JavaScript toolkits.</p>

<p>You can <a href="http://mankz.com/code/GlobalCheck.htm">see Framework Scanner in action here</a>.</p>

<p>Fleegix.js comes out looking pretty good in this online demo, with only 6 additional global symbols detected -- and as it turns out, 2 of those are false positives. One of those is an undeclared local variable which was leaking out into the global namespace (and has subsequently been fixed). The other is an old-style "onunload" which I can't find any references to in the code anywhere -- perhaps it existed in some plugin somewhere at some point in the past, I'm not sure.</p>

<p>The online demo includes an "Analyze your own scripts" feature, so I re-ran the test with the most up-to-date version of the library <a href="http://github.com/mde/fleegix-js-javascript-toolkit/tree/master">on GitHub</a>, and it correctly found only 4 global symbols: (<code>$</code></pre>, <code>$elem</code></pre>, <code>$text</code></pre>, and <code>fleegix</code></pre>).</p>

<p>This stacks up pretty well with Dojo 1.2.3 (5), JQuery 1.3 (2 -- presumably <code>jQuery</code></pre>, and <code>$</code></pre>, which they use as an alias for it), Prototype 1.6.0.3 (25, wow), YUI 2.6.0 (5), and MochiKit 1.3.1 (243 (robot Jesus!), or 11 with <code>__export__</code></pre> set to false).</p>

<p>Really nice to see Fleegix.js showing up with such illustrious company -- and with the magic of alphabetical order, it's right there at the top, sweet!</p>

<p>Framework Scanner is pretty cool -- since more people are mixing-and-matching toolkits, knowing what kind of impact they have on the global namespace is really helpful. It also gives you a good idea of whether the creators of the toolkit in question put much priority on "playing nicely with others."</p>]]>
           </body>
           <title>
               <![CDATA[Fleegix.js and Framework Scanner]]>
           </title>
           <publishedAt>2009-02-08T22:07:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2009-02-08-fleegix-js-and-framework-scanner</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>A big feature of the new <a href="http://seesmic.com/">Seesmic.com Webapp</a> is our auto-update feature which provides near-real-time updates in the UI of videos as they're posted.</p>

<p>Under the hood the auto-update uses simple long-polling of our XMPP service via BOSH, using <a href="http://metajack.wordpress.com/">Jack Moffitt's</a> excellent <a href="http://metajack.wordpress.com/2008/06/30/strophe-preview-xmpp-in-javascript/">Strophe.js</a> library to handle the nitty-gritty of connections, auth, and parsing all that tricksy XML output.</p>

<p>Pretty cool seeing those video posts pop into the UI over that sweet BOSH connection. But of course with that permanent long-running connection in the browser, we butt right up against <a href="http://cometdaily.com/2007/11/11/the-dreaded-2-connection-limit/">the dreaded two-connection limit</a>, and API calls to the backend are stuck going serially through the one remaining pipe. That really sucks a lot of the awesome out of the user-experience we're trying to bring.</p>

<p>The obvious solution was to move that dude to to a different subdomain so it's not permanently hogging half of the pipe to the backend. The <a href="http://en.wikipedia.org/wiki/Same_origin_policy">same-origin policy</a> for XHR calls in JavaScript throws a little bit of cold water on this plan, but like all things in the world of cross-browser Ajax apps, judicious application of a bit of ugly hackery will make things work.</p>

<p>In this case, the hackery is the fun and super-interesting world of <a href="http://jszen.blogspot.com/2005/03/cross-domain-security-woes.html">cross-domain iframe communication</a>. This technique has been around for a long time, but I've never had the pleasure of working with it. And by "pleasure," of course I mean "annoying, nagging pain, like a migraine that just won't go away."</p>

<p>The same-origin policy means pages served from different subdomains can't communicate with each other, but that's precisely what we need in this case -- we <em>need</em> to unload that BOSH connection to a different subdomain. Cross-domain iframe communication gets around this limitation by taking advantage of the fact that you can change the <code>document.domain</code></pre> (essentially the security context that JavaScript executes in) of a page after it reaches the browser.</p>

<p>The idea is pretty simple -- serve the page in an iframe from a subdomain, change <code>document.domain</code></pre> to match the hosting page. XHR objects in the iframe page don't change their notion of relative URLs, so they can still make calls back to the original subdomain server with no problem, but JavaScript can report those results back up to the parent page.</p>

<p>In practice, it's tweakier than that, with different browsers having different ideas about what exactly "match the hosting page" means. And as you might expect, it's Safari and Firefox at one end of the table, and IE way down at the other.</p>

<p>Here's the breakdown I found. Maybe this will save some other folks a few minutes of irritation.</p>

<h3>Firefox/Safari</h3>

<ul>
<li><p>TLD: They don't care if the parent page and the iframe <code>document.domain</code></pre> are a top-level domain or not, they just want them to match.</p></li>
<li><p>Setting the <code>document.domain</code></pre>: Bizarrely, you <em>have</em> to set the <code>document.domain</code></pre> on both the parent page and the iframe page <em>even if the parent page is already what you want.</em></p></li>
</ul>

<h3>Internet Explorer</h3>

<ul>
<li><p>TLD: Totally doesn't work unless both parent page and iframe page are using a top-level domain for the <code>document.domain</code></pre>.</p></li>
<li><p>Setting the <code>document.domain</code></pre>: Bizarrely, you <em>cannot</em> reset the document.domain of the parent page if it's already a TLD. Resetting it (even to the same value) will break the cross-iframe communication.</p></li>
</ul>

<p>Once I got through stubbing toes on all the annoying inconsistencies, communication back and forth between the iframe document and the parent worked great. Now we've got the two pages chit-chatting back and forth like two distant relatives at a family reunion who discover they both love Ronnie James Dio.</p>

<p>The browser still has to deal with the continuous open connection to the backend, but it's noticeable how much snappier the app is without BOSH sitting there Bogarting one of only two available connections to the main app domain.</p>]]>
           </body>
           <title>
               <![CDATA[BOSH and iframe cross-domain pain]]>
           </title>
           <publishedAt>2009-01-22T00:14:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2009-01-21-bosh-and-iframe-cross-domain-pain</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Like any self-respecting Web UI developer, I have a lovingly cultivated hatred of Internet Explorer.</p>

<p>IE and I go way back -- I've been developing for IE since version 3, and I have a fairly well evolved sense of sense of what breaks there. So it's always an occasion for rejoicing when I trip over something strange and new.</p>

<p>Some recent code-refactoring breakage (I moved a code loop and left a variable undeclared, sweet!) unearthed this little gem: IE (both 6 and 7) seems to have a built-in global symbol called <code>item</code></pre>. </p>

<p>It reports its type as <code>'string'</code></pre>, but appears to be an invokable function -- calling it with a random param passed yields the error: "Member not found":</p>

<div class="CodeRay">
  <div class="code"><pre>alert(<span class="r">typeof</span> item); <span class="c">// Alerts 'string', expected 'undefined'</span>
item(<span class="s"><span class="dl">'</span><span class="k">foo</span><span class="dl">'</span></span>); <span class="c">// Throws 'Member not found' error</span>
</pre></div>
</div>

<p>I'd love it if someone could enlighten me -- WTF is this 'item' thing?</p>

<p>It looks like some kind of vestigial <a href="http://en.wikipedia.org/wiki/Active_Scripting">Active Scripting</a> organ -- I did find a <a href="http://www.devguru.com/technologies/WSH/17386.asp">reference</a> to a default <code>item</code></pre> method of <code>WshArguments</code></pre> in <a href="http://en.wikipedia.org/wiki/Windows_Script_Host">Windows Script Host</a>, but nothing to explain, what, if anything it actually does in IE.</p>

<p>As a side note, IE6 is older than all my kids. And they're about to graduate college. Okay, not really -- the oldest is in first grade. But still.</p>]]>
           </body>
           <title>
               <![CDATA[WTF, global "item" symbol in IE]]>
           </title>
           <publishedAt>2008-11-25T10:13:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-11-25-wtf-global-item-symbol-in-ie</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>This past week I ran afoul of an interesting bug in Firefox 3 trying to serialize some stuff with <a href="http://js.fleegix.org/ref#fleegix.json.serialize">fleegix.json.serialize</a>.</p>

<p>Iterating over the properties of the DOMException (which for some inexplicable reason <a href="http://weblogs.asp.net/bleroy/archive/2008/04/23/what-s-that-exception-you-have-here.aspx">isn't an instance of a generic Error</a>, but that's another rant) reveals the existence of a a <code>location</code></pre> property. But sadly, much like <a href="http://en.wikipedia.org/wiki/Nigel_Tufnel">Nigel Tufnel's</a> Fender Bass VI, this property is not to be touched, or even looked at -- if you actually attempt to access the property directly, you get the wonderfully intuitive error, "Permission denied to create wrapper for object of class UnnamedClass."</p>

<p>As it turns out, this bug has already been reported -- it's <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=436953">Firefox bug 436953</a>.</p>]]>
           </body>
           <title>
               <![CDATA[Kerblooey accessing DOMException location property]]>
           </title>
           <publishedAt>2008-11-20T09:58:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-11-20-kerblooey-accessing-domexception-location-property</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Okay, so the docs are all polished up, and tarballs/zips are freshly cooked, piping hot from the oven, so here it is, <a href="http://downloads.fleegix.org/fleegix_js/releases/">Fleegix.js 0.5.0</a>. Mmm, tasty JavaScript.</p>

<p>The code name for this release is "Palace of ECMA Supremacy." Any questions or concerns regarding this release must include the code phrase, or they will not be responded to. Just kidding. Probably.</p>

<p>New features in this release include:</p>

<ul>
<li>Metaprogramming! New <a href="http://js.fleegix.org/ref#fleegix.extend">extend</a>, <a href="http://js.fleegix.org/ref#fleegix.mixin">mixin</a>, <a href="http://js.fleegix.org/ref#fleegix.clone">clone</a> methods in base.</li>
<li>New <a href="http://js.fleegix.org/ref#fleegix.string">string module</a></li>
<li>Even more arrayish-method goodness for the <a href="http://js.fleegix.org/plugins/hash/hash">fleegix.hash.Hash</a> sortable Hash plugin -- <a href="http://js.fleegix.org/plugins/hash/hash#reverse">reverse</a>, <a href="http://js.fleegix.org/plugins/hash/hash#splice">splice</a>, <a href="http://js.fleegix.org/plugins/hash/hash#push">push</a>, <a href="http://js.fleegix.org/plugins/hash/hash#pop">pop</a>, <a href="http://js.fleegix.org/plugins/hash/hash#unshift">unshift</a>, and <a href="http://js.fleegix.org/plugins/hash/hash#shift">shift</a></li>
<li><a href="http://js.fleegix.org/plugins/date/date">fleegix.date.Date</a> plugin can now load timezone data from JSON objects</li>
<li><a href="http://js.fleegix.org/ref#sniffing">User-agent sniffing</a> (yeah, we live in an imperfect world)</li>
<li>New <a href="http://js.fleegix.org/plugins/ejs">fleegix.ejs</a> module for EJS (embedded JavaScript) templates -- why let the server-side guys have all the templating fun?</li>
</ul>

<p>In addition to the new features, a vast number of bugs lost their lives in this latest release. <a href="http://www.workpump.com/bugcount/bugcount.html">As Hernando says</a>, "The bugs are enormous. There are an infinity of bugs." Feel free to peruse the <a href="http://downloads.fleegix.org/fleegix_js/releases/fleegix-0.5.0/ChangeLog">ChangeLog</a> for a roll call of the deceased, and details on the new-feature work.</p>]]>
           </body>
           <title>
               <![CDATA[Fleegix.js 0.5.0 released]]>
           </title>
           <publishedAt>2008-09-09T20:45:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-09-09-fleegix-js-0-5-0-released</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>In a surprising recent development, <a href="http://js.fleegix.org/">Fleegix.js</a> appears in the Six Revisions article, <a href="http://sixrevisions.com/javascript/promising_javascript_frameworks/">10 Promising JavaScript Frameworks</a>, showcasing "10 alternative and capable JavaScript frameworks/libraries to explore."</p>

<p>Fleegix.js came in at number 10 on the list -- and frankly given its status (er, lack of status?) as a bit player on the grand Ajaxy-toolkit stage, it's pretty cool to see it showing up on any lists at all.</p>

<p>The Six Revisions article has gotten a mention on Ajaxian, in a post called <a href="http://ajaxian.com/archives/the-javascript-framework-long-tail">The JavaScript Long Tail</a> -- very nice to see Ajaxian giving some love to what they describe as "new/up-and-coming frameworks."</p>

<p>Actually, Fleegix.js is not new -- some of the code has been around since about 2002 -- but "up-and-coming"? Yeah, I like the sound of that.</p>

<p>In reality, I think biggest value proposition in Fleegix.js for JavaScript developers is in its <a href="http://js.fleegix.org/plugins">plugins</a> -- like the Olson-timezone-enabled Date in <a href="http://js.fleegix.org/plugins/date/date">fleegix.date.Date</a>, the sortable Hash in <a href="http://js.fleegix.org/plugins/hash/hash">fleegix.hash.Hash</a>, or even the new embbeded JavaScript templates in <a href="http://js.fleegix.org/plugins/ejs">fleegix.ejs</a> -- all of which can be easily plugged into existing frameworks. </p>

<p>I would love to see more people using the code, and hacking on it as well. There is a <a href="http://fleegix-js.lighthouseapp.com/dashboard">Lighthouse app</a> for bug reports. If you're interested in pitching in, the Fleegix.js site has a page on <a href="http://js.fleegix.org/contribute">how to contribute</a>.</p>

<p>Be looking for a new release in the coming week.  But for now, anyway, I'm happy to see Fleegix.js occupying a spot at the "tip of the JavaScript long tail."</p>]]>
           </body>
           <title>
               <![CDATA[Fleegix.js, the tip of the JavaScript long tail]]>
           </title>
           <publishedAt>2008-09-08T15:35:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-09-08-fleegix-js-the-tip-of-the-javascript-long-tail</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I recently saw a nice blog post by Mike Cantelon on <a href="http://mikecantelon.com/story/javascript-syntax-checking-vim">integrating JSLint with Vim</a>, and since I spend most of my days hacking JavaScript in Vim, it was a no-brainer for me to want that integrated-JSLint awesomeness, and right now, dammit.</p>

<p>Of course I already had SpiderMonkey (<code>sudo apt-get install spidermonkey-bin</code></pre> for you Ubuntu/Debian types), and quickly downloaded the needed <a href="http://www.jslint.com/fulljslint.js">fulljslint.js</a> file. (I stuck it in <code>/usr/lib</code></pre>.)</p>

<p>However, once I started going through the steps to set it up, a couple of improvements occurred to me. </p>

<p>First of all, when I got to the point of calling JSLint from SpiderMonkey (a la <a href="http://blog.ianbicking.org/jslint-command-line.html">Ian Bicking's post</a>, I saved myself a step of indirection by making the script an actual executable, rather than passing it to the js executable. I just added the usual <a href="http://en.wikipedia.org/wiki/Shebang_(Unix">shebang</a>) line, and the path to the <code>js</code></pre> executable at the top. </p>

<p>Here's my whole <code>runjslint</code></pre> script, that I stuck in <code>/usr/bin</code></pre>:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="er">#</span>!<span class="rx"><span class="dl">/</span><span class="k">usr</span><span class="dl">/</span></span>bin/js
load(<span class="s"><span class="dl">'</span><span class="k">/usr/lib/fulljslint.js</span><span class="dl">'</span></span>);

<span class="r">var</span> body = arguments[<span class="i">0</span>];

<span class="r">var</span> result = JSLINT(body, {
  browser: <span class="pc">true</span>,
  forin: <span class="pc">true</span>
});
<span class="r">if</span> (result) {
 print(<span class="s"><span class="dl">'</span><span class="k">How are you gentlemen. :)</span><span class="dl">'</span></span>);
} <span class="r">else</span> {
 print(<span class="s"><span class="dl">'</span><span class="k">Somebody set up us the bomb! :/</span><span class="dl">'</span></span>);
}
print(JSLINT.report());</pre></div>
</div>

<p>Next, being a JavaScript guy, the idea of using a Python script to format the JSLint HTML output into plaintext seemed somehow less-than-satisfying.</p>

<p>I actually started to add a quick inline formatting step directly in the <code>js</code></pre> command-line script, but I quickly realized that the JSLint output had a pretty complicated structure, and simple splitting/removing-tags just wasn't going to cut it for me anyhow. I wanted something a little nicer.</p>

<p>Using Lynx (<code>sudo apt-get install lynx</code></pre>) seemed to me an obvious approach -- and as it turns out, at least under Linux it's easy to <a href="http://osdir.com/ml/web.lynx.devel/2006-08/msg00010.html">use Lynx as a filter to convert HTML output to plaintext</a> in a shell command. (I'm not sure how you'd do it under OSX or one of the other BSDish OS's, but I'd assume there's a way to make it work.)</p>

<p>Here's what I added to my .exrc, including the piping through <code>lynx</code></pre>, to create the filter:</p>

<div class="CodeRay">
  <div class="code"><pre>cabbr jslint !runjslint &quot;`cat %`&quot; \
  \| lynx --force-html /dev/fd/5 -dump 5&lt;&amp;0 \| less</pre></div>
</div>

<p>It was really cool to see how easily this could be done, and with these small improvements, it's even nicer.</p>

<p>I find myself JSLinting now pretty regularly throughout the day -- especially once I got JSLint to shut up about one-shot constructor functions for namespace objects. And I guess that's a pretty specific tweak that might be worth another post.</p>

<p>UPDATE</p>

<p>This post seems to have attracted some linkage, as evinced by the large number of apparently manually-added spam comments I've just had to remove.</p>

<p>The text is not machine-generated, and purports to respond to something actually in the post, but the link for the author is a spam link.</p>

<p>Comments for this article are now closed. If you have something relevant, do please send it to me via e-mail and I'll keep this updated.</p>

<p>UPDATE</p>

<p>Via e-mail (comments are closed due to spammer asshats) -- from <a href="http://whereisandy.com/">Andy Walker</a>, a hacked-up Rhino-based JSLint which can accept input from a pipe or as a redirect target:</p>

<p><a href="http://whereisandy.com/code/jslint">http://whereisandy.com/code/jslint</a></p>]]>
           </body>
           <title>
               <![CDATA[JSLint in Vim through Lynx]]>
           </title>
           <publishedAt>2008-09-06T21:50:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-09-06-jslint-in-vim-through-lynx</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>It's a Windmill revolution! (Get it? You see, Windmills are these things that go around and around -- they <em>revolve,</em> you see, so, um .... Yeah, that's terrible, I'll stop.) Actually there really are some revolutionary changes going with <a href="http://getwindmill.com">Windmill</a>, the Web-UI testing framework birthed at <a href="http://osafoundation.org/">OSAF</a>.</p>

<p>First of all they recently released <a href="http://www.getwindmill.com/archives/210">version 0.8.2</a>, with some great new features:</p>

<ul>
<li>Integrated Firebug Lite support</li>
<li>wxWindmill contrib application</li>
<li>Enhanced 'smart' recorder</li>
<li>Auto element-scroll-into-view to simulate actual use more closely</li>
</ul>

<p>The Windmill project has also moved to brand-new infrastructure, including a shiny new Web site at <a href="http://getwindmill.com/">http://getwindmill.com/</a></p>

<p>The core team is hard at work on more new-feature goodness, as well as relentlessly squashing bugs as they crop up. You can usually find them in IRC (#windmill on Freenode.net), or follow their progress on the <a href="http://groups.google.com/group/windmill-dev">developer mailing list</a>.</p>

<p>If you haven't checked out Windmill lately, you'll be pretty amazed to see how fast the improvements are piling up. Check out their <a href="http://www.getwindmill.com/features/windmill-introduction-video">introductory screencast</a> to see the newest Windmill release in action. You'll also find a handy <a href="http://www.getwindmill.com/features">side-by-side comparison</a> on the Windmill site which gives you an idea of Windmill's feature set compared with other testing solutions.</p>

<p>In short, the Windmill core team is kicking serious ass, and I'm really looking forward to seeing more Windmill awesomeness in the coming months.</p>]]>
           </body>
           <title>
               <![CDATA[Windmill revolution!]]>
           </title>
           <publishedAt>2008-09-06T00:17:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-09-06-windmill-revolution</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>We're using <a href="http://developer.yahoo.com/yui/">YUI</a> now at Seesmic. We were using my <a href="http://js.fleegix.org/">Fleegix.js</a> library, but as more developers come on board I think it's better to use something mainstream. YUI also has a large array of well-tested UI elements (Overlay, TabView, etc.) that make rapid development easier. </p>

<p>So far the transition has been relatively painless. YUI is massively frameworky and kind of ponderous -- but it is well documented, and it's pretty easy to get it to do what you need it to.</p>

<p>The glaring exception so far has been their implementation of publish/subscribe. Sure, YUI <em>has</em> <a href="http://developer.yahoo.com/yui/event/#customevent">custom events</a>. Any toolkit for building real apps (as opposed to Ajaxy pages or sites) needs it for keeping UI components decoupled.</p>

<p>Sadly, in the case of YUI, pub/sub is a bit of a mess -- custom events is a weird mish-mosh of function, scope, and params flying around, with no over-arching design that I can discern. </p>

<p>I keep thinking that the Yahoo (no, I won't put that fucking exclamation mark on the end -- that's! completely! stupid!) JS guys have to be smart, but when I see something like this I can't help but wonder what drugs they were on. The over-the-top ad-hoc-ness bears a strong resemblance to a good old-fashioned game of <a href="http://en.wikipedia.org/wiki/List_of_games_in_Star_Trek#Fizzbin">Fizzbin</a>.</p>

<p>I have used other pub/sub systems that don't suck. <a href="http://dojotoolkit.org/">Dojo</a>, for all its other imperfections, has a really uber eventing system with really nice pub/sub -- which is of course why I cloned its API for Fleegix.js's <a href="http://js.fleegix.org/ref#fleegix.event.publish">event.publish</a> and <a href="http://js.fleegix.org/ref#fleegix.event.subscribe">event.subscribe</a>.</p>

<p>Thankfully, JavaScript's meta-programming facilities make it pretty easy to consign YUI's Bizarro World custom-events API to code-purgatory. A simple wrapper around the <code>CustomEvent</code></pre> stuff gives you a simple and sane pub/sub interface.</p>

<p>Here's the code:</p>

<div class="CodeRay">
  <div class="code"><pre>YAHOO.util.Event.channels = {}; 
YAHOO.util.Event.subscribe = <span class="r">function</span> (channelName, obj, listenMethod) {
  <span class="r">var</span> getSubscriberMethod = <span class="r">function</span> () {
    <span class="r">return</span> <span class="r">function</span> (type, args, scopeObj) {
      scopeObj[listenMethod].apply(scopeObj, args);
    }   
  }
  <span class="r">if</span> (!<span class="pc">this</span>.channels[channelName]) {
    <span class="pc">this</span>.createChannel(channelName);
  }
  <span class="c">// Create a subscription for the passed object</span>
  <span class="pc">this</span>.channels[channelName].subscribe(getSubscriberMethod(), obj);
};
YAHOO.util.Event.publish = <span class="r">function</span> (channelName, paramObj) {
  <span class="r">if</span> (!<span class="pc">this</span>.channels[channelName]) {
    <span class="pc">this</span>.createChannel(channelName);
  }
  <span class="pc">this</span>.channels[channelName].fire(paramObj);
};
YAHOO.util.Event.createChannel = <span class="r">function</span> (channelName) {
  <span class="pc">this</span>.channels[channelName] =
    <span class="r">new</span> YAHOO.util.CustomEvent(channelName, <span class="pc">this</span>);
};</pre></div>
</div>

<p>This creates two methods you can use in the <code>YAHOO.util.Event</code></pre> namespace -- <code>publish</code></pre>, and <code>subscribe</code></pre>. Calling either one of these will automatically create the specified channel if it doesn't exist.</p>

<p>You use it like this:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">var</span> subscriber = <span class="r">new</span> <span class="r">function</span> () {
  YAHOO.util.Event.subscribe(<span class="s"><span class="dl">'</span><span class="k">someChannelName</span><span class="dl">'</span></span>,
    <span class="pc">this</span>, <span class="s"><span class="dl">'</span><span class="k">handlePublish</span><span class="dl">'</span></span>);
  <span class="pc">this</span>.handlePublish = <span class="r">function</span> (obj) {
    alert(obj.message);
  };  
}

<span class="r">var</span> publisher = <span class="r">new</span> <span class="r">function</span> () {
  <span class="pc">this</span>.sendMessage = <span class="r">function</span> (msg) {
    YAHOO.util.Event.publish(<span class="s"><span class="dl">'</span><span class="k">someChannelName</span><span class="dl">'</span></span>,
      {message: msg});
  }
};

publisher.sendMessage(<span class="s"><span class="dl">'</span><span class="k">foo</span><span class="dl">'</span></span>); <span class="c">// Alerts 'foo'</span></pre></div>
</div>

<p>This is a really minimal example, but you get the idea.</p>

<p>Basically this just lets you send an arbitrary package of stuff (data, functions -- anything you can stick in a JavaScript object)  to a named channel, and all the interested objects listening on that channel will receive it. Nice, simple pub/sub -- easy as pie.</p>

<p>I haven't really banged on this very heavily, so there may be some bumps in the road, but so far it's working like a champ -- publishing messages across the app, and staying out of the way.</p>

<p>Obviously too, there's a tiny bit of overhead added working through this wrapper -- but pub/sub is for macro-level events that function across your entire app, not micro-eventing within single components. The performance implications of using this wrapper should be pretty negligible.</p>

<p>It's a small price to pay for avoiding a game of Fizzbin.</p>]]>
           </body>
           <title>
               <![CDATA[Painless publish/subscribe with YUI custom events]]>
           </title>
           <publishedAt>2008-07-29T11:35:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-07-29-painless-publish-subscribe-with-yui-custom-events</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Handling server-side errors in Ajaxy Web apps has always been annoying. There is a <a href="http://www.google.com/search?hl=en&amp;q=ajax+error+handling&amp;btnG=Search">raft of articles on the subject</a>, and I've seen it brought up in numerous conference talks, too.</p>

<p>In <a href="http://www-128.ibm.com/developerworks/web/library/wa-ajaxintro3/">lots of articles</a>, the idea of 'handling' the error is limited to printing some scrap of text for the user (often in our favorite Philip-Glass-mimimalist piece of 'user interface,' the alert box). Super-cool, you're trying to cram something that usually occupies an entire Web page into a postage-stamp-sized square.</p>

<p>It's just not helpful getting back a bunch of formatted HTML instead of the data your Ajax UI is expecting.</p>

<h3>What flavor of FAIL?</h3>

<p>When something goes south on your server, you need to tell your clients a bit more than "oh, shit." Server-side FAIL comes in multiple flavors, just like 'Cokes' here in Texas. ("What kind of Coke do you want?" Yeah, it's silly, but I still giggle anytime I hear someone say 'pop' or 'soda.')</p>

<p>And as more Web clients begin to implement more RESTful interfaces, and implement them in more depth, this question of <em>what kind of failure</em> starts to be even more important, because there's a broader range of errors to consider, and they don't always mean there's been some kind of catastrophic breakage.</p>

<p>Looking at the XHR object status (or however you can get at the HTTP status code), that's a good start, but that doesn't really tell you that much about what exactly screwed up, or why -- so there's no real way to know what to do about it, or what to show to the end-users.</p>

<h3>Hammered error-detail doo-doo</h3>

<p>Your next problem then is how to hammer the error details into something usable for your app, and worthwhile for the end-user.</p>

<p>If your Ajax app requests some data, and the request succeeds, you get a nice string of parsable JSON data your code can consume -- but if something goes wrong on the server and you get back ... a big page of HTML markup. To quote Miracle Max: "While you're at it, why don't you give me a nice paper cut and pour lemon juice on it?"</p>

<p>In the early Ajax days, one method I used a lot for debugging was popping up an entirely new browser window and dumping the responseText into it. It's a pretty reasonable approach for development (until Firefox's new-window-in-a-tab breaks it, thanks, guys) but it's not really helpful for end-users in a production app.</p>

<p>Another fun 'solution' involves doing string comparisons or regex checks against that massive HTML hairball. Kind of like groping around incoherently for where you dropped your car keys at the party after your fifth beer. Not just sub-optimal -- more like anti-optimal.</p>

<h3>Nice work if you can get it</h3>

<p>If your client is really integrated with your server, you can tailor your error responses and client-side handling to work together. Nothing like writing everything yourself on both sides to make sure your shit actually works.</p>

<p><a href="http://chandlerproject.org/Developers/DownloadChandlerServer">Chandler server</a> returns errors in Atom format, so when I worked at OSAF I could count on JavaScript having access to a nice, brief message to display to end-users -- as well as more detailed info (a big ol' Java stack trace) that we could give the user a link to in the error dialog.</p>

<h3>Unfortunately we're out of 'zardoz.xml'</h3>

<p>What if you're not so lucky? What if you have to support different, disparate clients, and multiple data formats? Shouldn't your app provide error data in those same formats?</p>

<p>If your local Vietnamese restaurant can take your order in English, then it's pretty reasonble to expect they can tell you in English that they're out of <a href="http://en.wikipedia.org/wiki/Sriracha">Sriracha sauce</a> or whatever. (Like that would ever happen at any self-respecting Vietnamese place, right -- anyhow, you get the point.)</p>

<p>So if I ask for an XML file that turns out not to exist, it'd be pretty kick-ass to get back some XML that tells me so.</p>

<h3>Doing it with Merb</h3>

<p>I've been doing a lot of work lately with Merb, the Ruby Web-app development framework. It has pretty smart content-negotiation support, which makes it super-easy to provide data in multiple formats. It's also really customizable, so it turns out to be a snap in Merb to do format-specific error handling.</p>

<p>All you have to do is make some changes to the <code>Exceptions</code></pre> controller in <code>/app/controllers/exceptions.rb</code></pre>, and you can return errors to the client in whatever format the original request was in.</p>

<p>Here's the code:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">class</span> <span class="cl">Exceptions</span> &lt; <span class="co">Application</span>
  include <span class="co">Merb</span>::<span class="co">ResponderMixin</span>
  provides <span class="sy">:json</span>, <span class="sy">:xml</span>

  <span class="c"># handle NotFound exceptions (404)</span>
  <span class="r">def</span> <span class="fu">not_found</span>
    render_for_format
  <span class="r">end</span>

  <span class="c"># handle NotAcceptable exceptions (406)</span>
  <span class="r">def</span> <span class="fu">not_acceptable</span>
    render_for_format
  <span class="r">end</span>

  <span class="r">def</span> <span class="fu">render_for_format</span>
    format = content_type
    <span class="r">if</span> format == <span class="sy">:html</span>
      render <span class="sy">:format</span> =&gt; <span class="sy">:html</span>
    <span class="r">else</span>
      except = params[<span class="sy">:exception</span>]
      <span class="c"># Status code, e.g., 404</span>
      stat = except.class::<span class="co">STATUS</span>
      <span class="c"># Status text, e.g., &quot;Not Found&quot;</span>
      words = except.name.split(<span class="s"><span class="dl">'</span><span class="k">_</span><span class="dl">'</span></span>)
      words.each <span class="r">do</span> |w|
        w.capitalize!
      <span class="r">end</span>
      stat_text = words.join(<span class="s"><span class="dl">'</span><span class="k"> </span><span class="dl">'</span></span>)
      <span class="c"># Error message, e.g., &quot;Controller 'Zardoz' not found&quot;</span>
      msg = except.message
      data = { <span class="sy">:status</span> =&gt; stat,
        <span class="sy">:status_text</span> =&gt; stat_text,
        <span class="sy">:message</span> =&gt; msg }
      <span class="r">begin</span>
        display data
      <span class="c"># Handle formats the error-handler doesn't know about</span>
      <span class="r">rescue</span> <span class="co">NotAcceptable</span>
        render <span class="sy">:format</span> =&gt; <span class="sy">:html</span>
      <span class="r">end</span>
    <span class="r">end</span>
  <span class="r">end</span>
<span class="r">end</span></pre></div>
</div>

<h3>A few examples</h3>

<p>So a client making requests for a non-existent endpoint of "zardoz," in various formats, would see something like these:</p>

<p><code>/zardoz.json</code></pre></p>

<div class="CodeRay">
  <div class="code"><pre>{<span class="s"><span class="dl">&quot;</span><span class="k">status</span><span class="dl">&quot;</span></span>:<span class="i">404</span>,<span class="s"><span class="dl">&quot;</span><span class="k">message</span><span class="dl">&quot;</span></span>:<span class="s"><span class="dl">&quot;</span><span class="k">Controller </span><span class="k">'</span><span class="k">Zardoz</span><span class="k">'</span><span class="k"> not found</span><span class="dl">&quot;</span></span>,<span class="s"><span class="dl">&quot;</span><span class="k">status_text</span><span class="dl">&quot;</span></span>:<span class="s"><span class="dl">&quot;</span><span class="k">Not Found</span><span class="dl">&quot;</span></span>}</pre></div>
</div>

<p><code>/zardoz.xml</code></pre></p>

<div class="CodeRay">
  <div class="code"><pre><span class="pp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="ta">&lt;hash&gt;</span>
  <span class="ta">&lt;status</span> <span class="an">type</span>=<span class="s"><span class="dl">&quot;</span><span class="k">integer</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span>404<span class="ta">&lt;/status&gt;</span>
  <span class="ta">&lt;message&gt;</span>Controller 'Zardoz' not found<span class="ta">&lt;/message&gt;</span>
  <span class="ta">&lt;status-text&gt;</span>Not Found<span class="ta">&lt;/status-text&gt;</span>
<span class="ta">&lt;/hash&gt;</span>
</pre></div>
</div>

<h3>Content-negotiation goodies</h3>

<p>First of all, you have to include <code>ResponderMixin</code></pre> so you can get access to Merb's content-negotiation goodies. Then it's pretty simple to pull together the data you want to include in the response, and spit it out in the desired format.</p>

<h3>"I'm sorry, I don't speak FOAF"</h3>

<p>The rescue for the <code>NotAcceptable</code></pre> exception is kind of important. I guess it's a bit meta, but if your <em>exception controller itself</em> doesn't provide the requested format, you need to be able to fall back to a plain HTML-format error page.</p>

<p>You might wonder why you'd even bother trying to provide format-specific errors for the <code>not_acceptable</code></pre> action (this is where you end up when the client requests a format that's not supported). Well, there may be cases where your app speaks a particular format, but the <em>requested controller/action</em> does not. In that case, you can tell the client -- in the requested format -- that the requested format isn't supported. Fun.</p>

<p>It's a bit like the French dude I met in Thailand who responded to my question with "I'm sorry, I don't speak English" -- in what seemed to me to be perfect English. At least with the server-side error messages you know it's nothing personal -- and it's <em>probably</em> not because you're an ugly American.</p>

<h3>Caveats</h3>

<p>By default Merb doesn't actually bother parsing requests when they don't match any routes. This makes perfect sense of course -- but it means there's no <code>content_type</code></pre> for those requests, so you can't serve up your format-specific <code>NotFound</code></pre> errors for those.</p>

<p>If you want to have format-specific errors for all 404s, even for those that don't match any known routes, you can enable the default routes in <code>/config/router.rb</code></pre>.</p>

<h3>Okay, wrap it up, buddy ...</h3>

<p>Format-specific errors are a nice tool in the toolchest -- getting data in the format you asked for, even when something goes wrong, is kind of nice. Dealing with errors in your Ajaxy Web apps is annoying enough without having to trawl through a big pile of markup in an error HTML page.</p>

<p>As you can see from the code above, Merb makes this super-simple to do, but I'm sure there are all kinds of good ways to accomplish it in your language/framework of choice.</p>]]>
           </body>
           <title>
               <![CDATA[Format-specific server errors for your Ajax app using Merb]]>
           </title>
           <publishedAt>2008-06-26T21:48:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-06-26-format-specific-server-errors-for-your-ajax-app-using-merb</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Started kicking the tires this evening on <a href="http://www.appleinsider.com/articles/08/06/16/apples_open_secret_sproutcore_is_cocoa_for_the_web.html">SproutCore</a>, Apple's "Cocoa-inspired" JavaScript framework for buildling Web applications.</p>

<p>It looks pretty solid so far, although not nearly as far along as some of the older frameworks like Dojo, YUI, or even JQuery. The docs look pretty good, and rather than trying to take a server-language-agnostic approach, it integrates tightly with Ruby, which is personally appealing for me -- I like Ruby a lot, and my job at Seesmic has me doing a lot of server-side stuff in Ruby.</p>

<p>The <a href="http://www.sproutcore.com/documentation/hello-world-tutorial/">Hello World tutorial</a> is nicely done -- it does a good job of demonstrating how easily you can get a dynamic Web UI using some Ruby helpers in Erubis rhtml templates.</p>

<p>SproutCore works hard to provide some MVC-sanity for your Ajaxy Web app project, so files are organized logically into separate directories. Your JavaScript controller logic is kept in .js files in a controllers directory.</p>

<p>The only thing I've found remotely disagreeable so far with SproutCore is that, like the other Ruby-friendly library, Prototype, the syntax leans heavily toward JavaScript object literals for pseudo-class definitions.</p>

<p>You create your controller by passing an object containing the properties and methods desired to SC.Object.create, like so: </p>

<div class="CodeRay">
  <div class="code"><pre>HelloWorld.appController = SC.Object.create(
<span class="c">/** @scope HelloWorld.appController */</span> {
  greeting: <span class="s"><span class="dl">&quot;</span><span class="k">Hello World!</span><span class="dl">&quot;</span></span>,
  toggleGreeting: <span class="r">function</span>() {
    <span class="r">var</span> currentGreeting = <span class="pc">this</span>.get(<span class="s"><span class="dl">'</span><span class="k">greeting</span><span class="dl">'</span></span>);
    <span class="r">var</span> newGreeting = (currentGreeting === <span class="s"><span class="dl">'</span><span class="k">Hello World!</span><span class="dl">'</span></span>) ?
      <span class="s"><span class="dl">'</span><span class="k">I am on SproutCore!</span><span class="dl">'</span></span> : <span class="s"><span class="dl">'</span><span class="k">Hello World!</span><span class="dl">'</span></span>;
    <span class="pc">this</span>.set(<span class="s"><span class="dl">'</span><span class="k">greeting</span><span class="dl">'</span></span>, newGreeting);
  }
});</pre></div>
</div>

<p>I'm not keen on this syntax for creating objects for a couple of reasons.</p>

<p>One is the small-but-irritating trailing-comma problem with object literals. Some browsers, like Firefox, don't really mind them. Internet Explorer's JScript parser chokes on them like a fraternity pledge on his eighth shot of tequila.</p>

<p>When I lived in Japan, there was this local pub with a door that was ridiculously short -- the top of it hit me right around chest-level (I'm not a tall man), and you had to remember when entering and exiting to bend down to get through the door. I bumped my head on that thing time after time (as did all the locals -- it wasn't just a <em>gaijin</em> thing), cursing every time because I <em>knew</em> to duck my head.</p>

<p>The trailing-comma-separator problem in JavaScript is the same kind of problem as that goofy door -- you keep banging your head on it, even though you should <em>know</em> to be careful with it. Avoiding those object literals for something as ubiquitous as declaring your pseudo-classes makes it a lot less likely you'll be smacking your head on it over and over. </p>

<p>The other big downside of the object-literal syntax for pseudo-classes is that you don't get any local scoping, so you're reduced to using the underscore-propery-name convention to fake private variables. They're still public members, but you just pretend they're private. It's not unworkable, but it's much nicer to have access to actual private variables in your code.</p>

<p>There are a couple of alternatives to the object literal. You can use function objects in a couple of ways:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">var</span> foo;
<span class="c">// 1. Object literal</span>
foo = {}; 
<span class="c">// 2. Execute a function that returns an object</span>
foo = <span class="r">function</span> () { <span class="r">return</span> {}; }();
<span class="c">// 3. Use the 'new' keyword, return an obj by default</span>
foo = <span class="r">new</span> <span class="r">function</span> () {};</pre></div>
</div>

<p>All of those will return an object. Number two gives you private variables, but the final object you pass back still has to use the annoying object-literal syntax. Not much of a win.</p>

<p>Number three gives you private variables, and lets you use the normal idiomatic "this" syntax you're used to from writing plain old OO JavaScript. </p>

<p>Let's see how SproutCore's Hello World tutorial might turn out using the inline constructor function syntax from number three:</p>

<div class="CodeRay">
  <div class="code"><pre>HelloWorld.appController = SC.Object.create(
<span class="c">/** @scope HelloWorld.appController */</span> <span class="r">new</span> <span class="r">function</span> () {
  <span class="r">var</span> _strings = { 
    HELLO: <span class="s"><span class="dl">&quot;</span><span class="k">Hello World!</span><span class="dl">&quot;</span></span>,
    SPROUT: <span class="s"><span class="dl">&quot;</span><span class="k">I am on SproutCore!</span><span class="dl">&quot;</span></span>
  };  
  <span class="pc">this</span>.greeting = _strings.HELLO; 
  <span class="pc">this</span>.toggleGreeting = <span class="r">function</span> () {
    <span class="r">var</span> currentGreeting = <span class="pc">this</span>.get(<span class="s"><span class="dl">'</span><span class="k">greeting</span><span class="dl">'</span></span>);
    <span class="r">var</span> newGreeting = (currentGreeting === _strings.HELLO) ?
      _strings.SPROUT : _strings.HELLO;
    <span class="pc">this</span>.set(<span class="s"><span class="dl">'</span><span class="k">greeting</span><span class="dl">'</span></span>, newGreeting);
  };
});</pre></div>
</div>

<p>Notice I added a private variable, <code>_strings</code></pre>, to the controller pseudo-class. (I name private vars with a leading underscore to make it clear in my code that it's not a plain local variable -- but it's a real private variable.)</p>

<p>This also looks a lot better to me -- it's a wee bit more verbose with the repeated "this," but it looks to me more like the plain idiomatic JavaScript I'm used to, and there's no worry about smacking your head on that trailing-comma-separator problem.</p>

<p>SproutCore looks pretty reasonable so far. I hope to post more as I get more familiar with it.</p>]]>
           </body>
           <title>
               <![CDATA[Kicking the tires on SproutCore, not keen on the object literals]]>
           </title>
           <publishedAt>2008-06-19T01:33:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-06-19-kicking-the-tires-on-sproutcore-not-keen-on-the-object-literals</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Just added a bit of anti-spam fu to the comments field. Not sure how well it will work, but I'll give 'er a go and see.</p>

<p>Comments are back, as long as the spammers stay gone.</p>]]>
           </body>
           <title>
               <![CDATA[Comments are back -- die, spammer asshats]]>
           </title>
           <publishedAt>2008-06-18T11:34:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-06-18-comments-are-back-die-spammer-asshats</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Just sat down and watched Alex Russell's talk at Google I/O (from the end of last month) on the state of the browser, entitled <a href="http://www.youtube.com/watch?v=nG66hIhUdEU">Can We Get There From Here?</a> As always, Alex did a great job of weaving the disparate factors in play (and the weird, tweaky specifics that come along with them) into an interesting and understandable whole.</p>

<p>A few comments I thought worth jotting down -- maybe nits to pick.</p>

<h3>Where is "there"?</h3>

<p>In the talk, as in previous blog posts, Alex talks about all of us Web devs wanting "new stuff in the browser," and wondering who we need to bug to get it in there. He rightly points out that we can't count on the standards bodies to drive the process of innovation forward.</p>

<p>I'd like to qualify the Christmas wish-list desire for "new stuff" in the browser by pointing out that what we all really want is "the same new stuff, in all the different browsers the users actually use."</p>

<p>The competition from multiple browsers is messy -- and granted, the standards bodies are an actual drag on the innovation process -- but they force the various players to decide <em>together</em> which "new stuff" goes in, and what that new stuff looks like.</p>

<p>The alternative is the monoculture like Microsoft gave us in IE (and, one could argue like Adobe/Microsoft are trying to do with Flash/Silverlight), that lets us do a lot of cool stuff really quickly and conveniently -- until the last credible shred of competition is killed off, and we see years pass with no new features appearing.</p>

<p>In the talk, Alex mentions in passing that he wonders what such a monoculture would look like if it were an open-source browser.</p>

<p>I wonder if such a thing is even possible, given the openness, and the freedom (or, some might argue, the constant urge) to fork inherent in the open-source development paragdigm. All it takes is a couple of really smart guys with an opinion to create credible competitive pressure -- and we all know there's no shortage of those guys in open source. GNOME or KDE? Ubuntu or Fedora? Suse? Everybody's got a slight variation of the idea that they think is better than the others.</p>

<h3>How fast are we getting there?</h3>

<p>We all feel the need for speed -- that satisfaction of taking advantage of a cool new feature we haven't gotten to use before in our apps. "Oooh, look at the shiny!"</p>

<p>But it's worth pointing out that one of the reasons Web development has become so ubiquitous, and gathered such momentum behind it, is paradoxically <em>because</em> of that weirdly long period of statis after Microsoft squashed Netscape, when IE stagnated.</p>

<p>I was building browser-based app UIs during the initial round of browser wars, and it was kind of confusing keeping up with the browser revs and their competing, kind-of-overlapping, non-standard new features.</p>

<p>I don't exactly get all misty-eyed at the thought of all those "document.layers vs. document.all" branches in the code, and I'm a even a guy who's actually excited to get the "new stuff." Think about the corporate IT types -- in large organizations, change is expensive, no matter if some guy is telling you there's a big load of awesome in that change.</p>

<p>In some big companies, even rolling out a new version of IE is a huge deal (Hey Oracle, are y'all <em>still</em> sticking with IE6?) -- back in my days at KnowledgeWire I can remember dealing with the inevitable surly corporate IT types who balked at the idea of even rolling out a new version of the Shockwave plugin. Not a whole new frigging browser, just a plugin.</p>

<p>Auto-update is great and all, but behind a big corporate firewall, all bets are off, because change is a pain in the ass for these guys.</p>

<p>Again, the standards bodies aren't exactly playing Prometheus of Innovation, bravely bringing the fire of "new stuff" to mortals, but they provide a safe, measured rate of change that the IT guys can point their bosses to -- "Hey look, this 'JSON' thing is an IETF standard." With that to point to, the likelihood is lower they'll get shitcanned if something horrible and unforeseen happens during the change.</p>

<h3>View Source as the signifier</h3>

<p>Alex mentioned the idea of Ctrl/Cmd+U for viewing the document source as a possible benchmark for conformance with the idea of "Webishness," contrasting that with Flash/Silverlight apps that are basically big ol' binary black-boxes.</p>

<p>I think it's worth being a little more specific and possibly replacing the simple View Source benchmark with the idea of "decomposability."</p>

<p>Even Ajax-heavy Web apps with nothing but "head, script tags, body" are stlll put together out of plaintext, and can be taken apart pretty easily to see how they tick, using either normal text editors, or freely available browser extensions like Firebug or the Web Developer Toolbar.</p>

<p>Sure, there's View Source -- but there's also View Generated Source. Nothing like that exists in Flash/Silverlight Land. (Okay, so it's really a continuum with stuff like decompillers way, way, way at the other end, but those aren't things you can expect normal humans to use.)</p>

<p>That kind of decomposability is actually another thing that fosters the development of that bustling bazaar of workaday devs that Alex talks about, making all that noise at the base of the ivory tower and irritating all the hardcore-developer dudes inside.</p>

<p>In fact, the simple fact of being able to take stuff apart with free tools gives any of those workaday dudes with half a clue and some persistence (okay, and the ability to read and follow instructions) entre into that tower.</p>

<p>That's right, you don't have to have a degree, or know the secret handshake or anything, to do this stuff (<a href="http://www.zedshaw.com/rants/rails_is_a_ghetto.html">douchebag comments from disgruntled drama-queen developers</a> notwithstanding). In fact, you can even have an English degree, or something stupid like that.</p>

<p>So the real importance isn't whether there's a lot of stuff right on the page to look at when you do Ctrl/Cmd+U -- sure, that's an easy and obvious indicator of the height of the barrier to entry -- but a more meaningful question is "can you take it apart?" and "how much do the tools cost?"</p>

<h3>Conclusion</h3>

<p>Alex really did an incredible job of distilling a bunch of really complicated stuff down into something digestible. If you have about an hour, and are interested in where we're headed with browser-based apps, you owe it to yourself to check out his talk.</p>

<h3>A final quibble</h3>

<p>NT4 actually shipped with IE2, not IE3. I don't remember anyone actually using it, but that's what was on the installation CD.</p>]]>
           </body>
           <title>
               <![CDATA[Alex Russell's talk at Google I/O 2008 -- comments, nits, and a quibble]]>
           </title>
           <publishedAt>2008-06-17T23:52:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-06-17-alex-russell-s-talk-at-google-i-o-2008-comments-nits-and-a-quibble</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Comments are currently down because of the usual spammer asshats posting spurious comments to plug the usual bizarre shit you'd never imagine anyone would actually buy.</p>

<p>PmpknPi is nicely minimalist, so it should be easy to hack in some kind of spammer-asshat protection -- if someone hasn't already.</p>]]>
           </body>
           <title>
               <![CDATA[Comments are shut down]]>
           </title>
           <publishedAt>2008-06-17T23:47:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-06-17-comments-are-shut-down</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Time for a change -- I've been needing to move my blog to a different server for awhile now, so I'm using this opportunity to change from <a href="http://www.typosphere.org/">Typo</a> (a Rails-based blog platform) to <a href="http://pmpknpi.com/">PmpknPi</a>, which advertises itself as "A RESTful Blog API written in Merb."</p>

<p>If you've a techie who's been hiding under a rock, and don't know what <a href="http://merbivore.com/">Merb</a> is, it's an MVC Web-app development framework written in Ruby. It's basically a competing/complementary framework to Rails -- much more minimalist and performance-oriented.</p>

<p>I'm running this blog on Merb with the <a href="http://code.macournoyer.com/thin/">Thin Ruby Web server</a>, a small, fast, event-driven HTTP server written in Ruby.</p>

<p>Merb is what we're using to build a lot of the <a href="http://seesmic.com/login">Seesmic Web app</a>, including the Ajax Web UI that's my primary focus. </p>

<p>We've been hard at work at Seesmic building out our <a href="http://wiki.seesmic.com/wiki/index.php/SeesmicAPI_Documentation">REST API</a>, which at least in part explains the dead air on this blog. (Twitter is probably another good target for finger-pointing on that count.)</p>

<p>Anyhow, with the switch of this blog to PmpknPi, I lose a lot of the bloat of both Rails and Typo, and should have something a bit more hackable. I'll also get something I should have put a premium on long, long ago -- code syntax highlighting from the excellent <a href="http://coderay.rubychan.de/">CodeRay</a> library. 'Bout frigging time.</p>]]>
           </body>
           <title>
               <![CDATA[Up and running with PmpknPi]]>
           </title>
           <publishedAt>2008-04-09T00:27:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-04-09-up-and-running-with-pmpknpi</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>On Tuesday of this week, OSAF announced a <a href="http://blog.chandlerproject.org/2008/01/08/osaf-transitions/">significant restructuring</a> of the organization. OSAF is now moving forward into a new phase of its existence with a smaller team -- a team that I will not be a part of.</p>

<p>I'm extremely proud of my work at OSAF, and what our small team was able to accomplish on <a href="http://chandlerproject.org/Developers/DownloadChandlerServer">Chandler Server</a> in such a short time. However, I had been thinking lately that it might be time to consider other possibilities -- so when the reorg began, I decided OSAF would be better served by letting me go, and keeping people who are tightly focused on the goals of the project.</p>

<p>My life has been incredibly enriched by all of the people I've worked with at OSAF, and I'm proud of the work I've done -- both on Chandler Server, and on the <a href="http://windmill.osafoundation.org/">Windmill</a> Web-app testing framework. I will of course be following the progress of Chandler with great interest, and will be offering whatever help or assistance I can to the Chandler developers and community.</p>

<p>I'm sure it won't take long for my fellow former OSAFers to get snapped up by various cool ventures. Bay Area tech companies are likely all salivating at the prospect of these brilliant people now out looking for jobs.</p>

<p>As for me, thanks to a kind introduction from one of those ex-OSAFers, <a href="http://code-bear.com/bearlog/">Mike "Bear" Taylor</a>, I am pleasantly surprised to find myself already employed, working on something new and pretty damned exciting. Starting January 16th, I will be working at <a href="http://www.seesmic.com/">Seesmic</a>, a startup company doing some <a href="http://www.crunchbase.com/company/seesmic">very interesting stuff</a> with Web video.</p>

<p>The service is still pre-alpha. (no, I don't have any invitation codes yet :)), and I'll be working on an Ajaxy Web UI for the service. I'll be blogging about the new job as things develop --  it's a startup, I'm hoping and expecting that things will be moving quickly.</p>

<p>Updated: here are some links to the various news items regarding OSAF's reorg:</p>

<ul>
<li><a href="http://blog.chandlerproject.org/2008/01/08/osaf-transitions/">Katie's original announcement</a></li>
<li><a href="http://blog.kapor.com/?p=77">Mitch's blog post</a></li>
<li><a href="http://www.wordyard.com/2008/01/11/osaf-cuts-back/">Scott Rosenburg's thoughtful dissection</a></li>
<li><a href="http://news.google.com/news/url?sa=t&amp;ct=us/0-1&amp;fp=4788083e6d38ca64&amp;ei=2gSIR7OMEoz4-wH4_73ACw&amp;url=http%3A//www.news.com/8301-10784_3-9847739-7.html%3Ftag%3Dnefd.top&amp;cid=1126131594">Ghoulish triumphalism from Matt Assay</a></li>
<li><a href="http://whydoeseverythingsuck.com/2008/01/mitch-kapors-weekend-at-bernies.html">Needlessly mean-spirited critique from Hank Williams</a></li>
<li><a href="http://www.nytimes.com/idg/IDG_002570DE00740E18002573CC004F945F.html?ref=technology">NYT's flat statement of the facts</a></li>
</ul>]]>
           </body>
           <title>
               <![CDATA[OSAF 2.0 to Seesmic pre-alpha]]>
           </title>
           <publishedAt>2008-01-11T20:15:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-01-11-osaf-2-0-to-seesmic-pre-alpha</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Somehow amidst all the chaos that is currently my life, I've packaged up version 0.4.1 of Fleegix.js for release. You can download the new release at the <a href="http://js.fleegix.org/download">usual location</a>.</p>

<p>This is primarily a bugfix release. Here are some of the fixes and improvements:</p>

<ul>
<li>Fixes in the <a href="http://js.fleegix.org/plugins/hash/hash">hash plugin</a> for Safari 2's ridiculous <a href="http://www.t0asted.com/sblog/index.php?entry=entry071026-140124">Math.random bug</a></li>
<li>Updates to the <a href="http://js.fleegix.org/plugins/xml">xml parser plugin</a> to handle CDATA and comment nodes properly</li>
<li>Fixes for multi-selector class attributes with <code>css.addClass</code></pre></li>
<li>Improved caching in <a href="http://js.fleegix.org/plugins/date/date">timezone-enabled Date plugin</a>, new <code>getTimezoneAbbreviation</code></pre> method</li>
<li>Fixes for previous-year inclusion in rule-hits in the <a href="http://js.fleegix.org/plugins/date/date">timezone-enabled Date plugin</a></li>
<li>New option to squelch errors from execution of handlers in <code>event.listen</code></pre></li>
<li>A bunch of new unit tests that work with <a href="http://windmill.osafoundation.org/">Windmill's</a> JavaScript test framework</li>
</ul>]]>
           </body>
           <title>
               <![CDATA[Fleegix.js JavaScript Toolkit 0.4.1 release]]>
           </title>
           <publishedAt>2008-01-10T18:41:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-01-10-fleegix-js-javascript-toolkit-0-4-1-release</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Tim Bray has a nice post that <a href="http://www.tbray.org/ongoing/When/200x/2008/01/04/Predictions-PHP">succinctly describes</a> the situation with PHP in 2008 -- why it's still popular, but its growth continues to slow.</p>

<p>I think that the various pluses and minuses could be reduced even more by simply thinking of PHP as the McDonald's of programming languages.</p>

<p>PHP, like McDonald's, is really, really convenient, -- it's pretty much already installed everywhere you go. Deployment, like eating at Mickey Dee's, is a breeze.</p>

<p>And maybe I'll be totally ostracized for saying it, but I don't particularly mind using PHP to set up a quickie Web site with some simple templating. It's dead simple, and I know stuff will just work.</p>

<p>Like the food at McDonald's, using PHP isn't that bad every once in a while -- but I wouldn't want to eat it every day. And I'm pretty sure a steady diet of it will kill you.</p>]]>
           </body>
           <title>
               <![CDATA[PHP is the McDonald's of programming languages]]>
           </title>
           <publishedAt>2008-01-07T17:20:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-01-07-php-is-the-mcdonalds-of-programming-languages</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>In a Rails app I was recently working on, the data model called for associating sets of related business objects. Initially it looked like I was going to have to handle it with sub-classing.</p>

<h3>Sub-classing and prog-rock keyboardists</h3>

<p>I was kind of reluctant to do this in a Rails app, because the traditional Rails approach to representing an object hierarchy uses <a href="http://wiki.rubyonrails.org/rails/pages/SingleTableInheritance">single-table inheritance</a> -- dumping a column for every possible attribute for every possible sub-class into one table.</p>

<p>This kind of ugliness is an example of the Rick Wakeman Brute Force Approach: no worries about those primitive synths that can only provide one patch at a time, just <a href="http://rwcc.com/graphics/gallery/photo008.jpg">drag an ass-load of them with you</a> whenever <a href="http://rwcc.com/graphics/gallery/photo003.jpg">you go on the road</a>. It gets the job done, but it's not particularly elegant.</p>

<p>In my particular case, sub-classing might have actually worked, if I could have endured the single-table-inheritance stink. But what about cases you may want to group types of things in your app that have a less obvious relationship than can be represented with a hierarchy chain?</p>

<h3>Promiscuity is so much nicer</h3>

<p>Thankfully, a very nice way to do this sort of thing exists in the form of <a href="http://wiki.rubyonrails.org/rails/pages/UnderstandingPolymorphicAssociations">polymorphic associations</a> (also called "promiscuous associations," yay!), which allow you a lot of the same capabilities as an inheritance hierarchy, but gives you more flexibility in creating relationships between objects.</p>

<p>With polymorphic associations, you can literally connect any type of thing in your data model to any other type. A common example used to describe this is tagging, where a given tag could potentially be associated with any type of thing in your data model.</p>

<p>It almost makes you a little drunk with power, this newfound ability to link <em>this</em> to <em>that</em> and <em>that</em> to <em>the other thing over there.</em> You can almost imagine, with <a href="http://www.youtube.com/watch?v=lI_whOzMu1c">all due apologies to the Pythons</a>, a Royal Society for Associating Things With Other Things.</p>

<h3>The has<em>many</em>polymorphs plugin</h3>

<p>Using polymorphic associations without any special help is possible in Rails, but it is <a href="http://blog.hasmanythrough.com/2006/4/3/polymorphic-through">somewhat limited</a>. I found that what I needed to do required the use of the excellent <a href="http://blog.evanweaver.com/files/doc/fauna/has_many_polymorphs/files/README.html">has<em>many</em>polymorphs</a> plugin developed by <a href="http://blog.evanweaver.com/about">Evan Weaver</a>.</p>

<p>If you find yourself reading the docs and getting utterly confused the first time through, as I did, you can check out Pratik Naik's <a href="http://m.onkey.org/2007/8/14/excuse-me-wtf-is-polymorphs">helpful tutorial</a> that does a really nice job of laying it all out.</p>

<h3>Dude, where's my DB?</h3>

<p>The one piece I found missing in all the docs and tutorials for the has<em>many</em>polymorphs plugin was anything that showed what the corresponding database tables should look like, or how to use Rails migrations to set them up.</p>

<p>(There is a helpful, albeit minimal, example in the plugin source code examples/ directory for a simple single-sided association that pointed me in the right direction.)</p>

<p>I figured it might be helpful for other people using the plugin to see some migration examples. It might save them some of the time I spent futzing with things to get it all working.</p>

<h3>Single-sided associations</h3>

<p>Single-sided polymorphic associations are the simpler of the two kinds, where many types of things are associated with a single other type.</p>

<p>Say I'm writing an e-learning app, and I have <em>courses,</em> <em>exams,</em> and <em>seminars,</em> all of which might be assigned to a <em>person</em> to take. My model would look like this:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">class</span> <span class="cl">Course</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
<span class="r">end</span>
<span class="r">class</span> <span class="cl">Exam</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
<span class="r">end</span>
<span class="r">class</span> <span class="cl">Seminar</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
<span class="r">end</span>

<span class="r">class</span> <span class="cl">TasksPerson</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
  belongs_to <span class="sy">:person</span>
  belongs_to <span class="sy">:assignment</span>,
    <span class="sy">:polymorphic</span> =&gt; <span class="pc">true</span>
<span class="r">end</span>

<span class="r">class</span> <span class="cl">Person</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
  has_many_polymorphs <span class="sy">:assignments</span>,
    <span class="sy">:from</span> =&gt; [<span class="sy">:courses</span>, <span class="sy">:exams</span>, <span class="sy">:seminars</span>],
    <span class="sy">:through</span> =&gt; <span class="sy">:tasks_people</span>
<span class="r">end</span></pre></div>
</div>

<p>And the migration would look like this:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">class</span> <span class="cl">TasksPeople</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Migration</span>
  <span class="r">def</span> <span class="pc">self</span>.up
    create_table <span class="sy">:tasks_people</span> <span class="r">do</span> |t|
      t.column <span class="sy">:person_id</span>, <span class="sy">:integer</span>
      t.column <span class="sy">:assignment_id</span>, <span class="sy">:integer</span>
      t.column <span class="sy">:assignment_type</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:people</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:courses</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:exams</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:seminars</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>
  <span class="r">end</span>
  <span class="r">def</span> <span class="pc">self</span>.down
    drop_table <span class="sy">:tasks_people</span>
    drop_table <span class="sy">:people</span>
    drop_table <span class="sy">:courses</span>
    drop_table <span class="sy">:exams</span>
    drop_table <span class="sy">:seminars</span>
  <span class="r">end</span>
<span class="r">end</span></pre></div>
</div>

<p>Once you've got that set up, you can try it out in the console to see if stuff is working:</p>

<div class="CodeRay">
  <div class="code"><pre>&gt;&gt; c = <span class="co">Course</span>.create(<span class="sy">:name</span> =&gt;
  <span class="s"><span class="dl">&quot;</span><span class="k">How Not To Get Eaten By An Alligator</span><span class="dl">&quot;</span></span>)
&gt;&gt; e = <span class="co">Exam</span>.create(<span class="sy">:name</span> =&gt;
  <span class="s"><span class="dl">&quot;</span><span class="k">Zombie Army Attack Preparedness</span><span class="dl">&quot;</span></span>)
&gt;&gt; p = <span class="co">Person</span>.create(<span class="sy">:name</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">Ravi Shankar</span><span class="dl">&quot;</span></span>)
&gt;&gt; p.assignments.push(c)
&gt;&gt; p.assignments.push(e)
&gt;&gt; p.assignments.length =&gt; <span class="i">2</span></pre></div>
</div>

<p>Woohoo, Ravi has two assignments, just like you'd expect.</p>

<p>The beauty of this is that now I can assign courses, exams, seminars -- or anything else I deem "tasky" -- to people in my app, without having to wrangle the unwieldiness of shoving all that taskiness into a single table.</p>

<h3>Double-sided associations</h3>

<p>This is where it gets all wacky -- where multiple different types of things can be associated with other, multiple different types of things. Mass chaos ensues -- but in a good way.</p>

<p>Imagine now that e-learning app has grown and I need to make more complicated kinds of assignments. I need to be able to assign those different types of tasks (courses, exams, seminars) to individuals, or to groups -- say, for example, to <em>people,</em> <em>jobs,</em> and <em>organizations.</em></p>

<p>(For anyone who worked with me back in the <a href="http://www.knowledgewire.com/">KnowledgeWire</a> days, this is a nice trip down memory lane.)</p>

<p>This is a good example of a case where simple sub-classing would be conceptually awkward and weird -- people, jobs, and entire organizations aren't particularly similar things. The only thing they really have in common in this data model is their ability to have things assigned to them.</p>

<p>The model code would look like this:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">class</span> <span class="cl">Course</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
<span class="r">end</span>
<span class="r">class</span> <span class="cl">Exam</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
<span class="r">end</span>
<span class="r">class</span> <span class="cl">Seminar</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
<span class="r">end</span>
<span class="r">class</span> <span class="cl">Person</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
<span class="r">end</span>
<span class="r">class</span> <span class="cl">Job</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
<span class="r">end</span>
<span class="r">class</span> <span class="cl">Organization</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
<span class="r">end</span>

<span class="r">class</span> <span class="cl">AssignmentsAssignee</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Base</span>
  belongs_to <span class="sy">:assignment</span>, <span class="sy">:polymorphic</span> =&gt; <span class="pc">true</span>
  belongs_to <span class="sy">:assignee</span>, <span class="sy">:polymorphic</span> =&gt; <span class="pc">true</span>

  acts_as_double_polymorphic_join(
    <span class="sy">:assignments</span> =&gt;[<span class="sy">:courses</span>, <span class="sy">:exams</span>, <span class="sy">:seminars</span>],
    <span class="sy">:assignees</span> =&gt;[<span class="sy">:people</span>, <span class="sy">:jobs</span>, <span class="sy">:organizations</span>]
  )
<span class="r">end</span></pre></div>
</div>

<p>And the migration would be like this:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">class</span> <span class="cl">AssignmentsAssignees</span> &lt; <span class="co">ActiveRecord</span>::<span class="co">Migration</span>
  <span class="r">def</span> <span class="pc">self</span>.up
    create_table <span class="sy">:assignments_assignees</span> <span class="r">do</span> |t|
      t.column <span class="sy">:assignment_id</span>, <span class="sy">:integer</span>
      t.column <span class="sy">:assignment_type</span>, <span class="sy">:string</span>
      t.column <span class="sy">:assignee_id</span>, <span class="sy">:integer</span>
      t.column <span class="sy">:assignee_type</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:people</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:jobs</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:organizations</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:courses</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:exams</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>
    create_table <span class="sy">:seminars</span> <span class="r">do</span> |t|
      t.column <span class="sy">:name</span>, <span class="sy">:string</span>
    <span class="r">end</span>

  <span class="r">end</span>
  <span class="r">def</span> <span class="pc">self</span>.down
    drop_table <span class="sy">:assignments_assignees</span>
    drop_table <span class="sy">:people</span>
    drop_table <span class="sy">:jobs</span>
    drop_table <span class="sy">:organizations</span>
    drop_table <span class="sy">:courses</span>
    drop_table <span class="sy">:exams</span>
    drop_table <span class="sy">:seminars</span>
  <span class="r">end</span>
<span class="r">end</span></pre></div>
</div>

<p>Now let's hop back into the console and see if this stuff all works:</p>

<div class="CodeRay">
  <div class="code"><pre>&gt;&gt; c = <span class="co">Course</span>.create(<span class="sy">:name</span> =&gt;
  <span class="s"><span class="dl">&quot;</span><span class="k">Life and Times of the Three Stooges</span><span class="dl">&quot;</span></span>)
&gt;&gt; s = <span class="co">Seminar</span>.create(<span class="sy">:name</span> =&gt;
  <span class="s"><span class="dl">&quot;</span><span class="k">LARPing for Fun and Profit</span><span class="dl">&quot;</span></span>)
&gt;&gt; p = <span class="co">Person</span>.create(<span class="sy">:name</span> =&gt;
  <span class="s"><span class="dl">&quot;</span><span class="k">Henry Kissinger</span><span class="dl">&quot;</span></span>)
&gt;&gt; o = <span class="co">Organization</span>.create(<span class="sy">:name</span> =&gt;
  <span class="s"><span class="dl">&quot;</span><span class="k">Australopithecus Unlimited</span><span class="dl">&quot;</span></span>)
&gt;&gt; p.assignments.push(c)
&gt;&gt; p.assignments.push(s)
&gt;&gt; p.assignments.length =&gt; <span class="i">2</span>
&gt;&gt; o.assignments.push(c)
&gt;&gt; o.assignments.push(s)
&gt;&gt; o.assignments.length =&gt; <span class="i">2</span></pre></div>
</div>

<p>Very nice. I can give the same assignments to both Henry Kissinger and to the entire Australopithecus Unlimited organization.</p>

<p>I can assign any of these tasky things to a person, job, or organization in the app. And also interestingly, I can do the reverse:</p>

<div class="CodeRay">
  <div class="code"><pre>&gt;&gt; e = <span class="co">Exam</span>.create(<span class="sy">:name</span> =&gt;
  <span class="s"><span class="dl">&quot;</span><span class="k">Apple Fanboy Test</span><span class="dl">&quot;</span></span>)
&gt;&gt; e.assignees.push(p)
&gt;&gt; e.assignees.push(o)
&gt;&gt; e.assignees.length =&gt; <span class="i">2</span></pre></div>
</div>

<h3>Gotchas</h3>

<p>One gotcha I noticed was that migrations wouldn't run to set up the database properly with the has<em>many</em>polymorphs plugin loaded. Looks like it's some kind of circular dependency issue. In any case, leaving the plugin require statement out of environment.rb until after setting up the DB is a workaround for this problem.</p>

<h3>Wrapping up</h3>

<p>There you have it. A nice, flexible way to create associations between loosely related types in your model. No ugly sub-classing stuff by trying to shoehorn every related type into one table.</p>

<p>There are some other nice tutorials and docs online to help you, but I couldn't find any that include the migration scripts above. I hope this helps save somebody some time.</p>]]>
           </body>
           <title>
               <![CDATA[Rails polymorphic associations and migrations]]>
           </title>
           <publishedAt>2008-01-03T05:06:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2008-01-03-rails-polymorphic-associations-and-migrations</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I recently participated in <a href="http://www.flossusability.org/wiki.pl?Sprint200711Agenda">FLOSS Usability Sprint V</a>, an event run by the <a href="http://www.flossusability.org">FLOSS Usability</a> organization to foster better usability in open-source software, and to encourage collaboration between usability/design/UX practitioners and the free/libre/open-source community.</p>

<p>Open-source software in general is sadly not known for its stellar usability, so this sort of event is really important -- both for the short-term aim of improving our UIs, and the long-term aim of developing some awareness of basic usability tenets in the open-source community. </p>

<p>Developers need to know that design and usability are not simply window-dressing, and they're not something you glue on after the fact. Attention to usability needs to be built right into the development process from the get-go -- including filing bugs about usability, and educating developers about basic usability principles.</p>

<p>The event was hosted by Google, and this was my first trip to the Google campus. I can see why so many people love working there. Google really made sure things went smoothly for us, and it was a great environment for collaboration and discussion. </p>

<p>The Mozilla Corporation hosted some beer-and-food happy hours that gave us a chance to continue discussions in a bit more informal atmosphere. It's always amazing to me how much of a difference that kind of face-to-face contact makes when so much of your communication happens with people over the phone or in text.</p>

<p>We were paired up with some really nice folks from the Oracle Usability Group, who were actually kind enough to let us have some use of their Usability Lab for testing Chandler Server's Web UI. </p>

<p>The Oracle guys were super-nice, and we had a ton of fruitful interaction with them. We got some good hard data about which parts of the UI work, and which parts don't -- and some ideas for improvement in a lot of different areas.</p>

<p>We focused on a particularly problematic piece of the Web UI -- calendar overlays, which are really a complicated design problem to solve. We whiteboarded a bunch of different approaches with the aim of trying to make things clearer than the design we currently have. You can see <a href="http://www.flossusability.org/wiki.pl?ChandlerUsability">graphics of all the whiteboard designs here</a>.</p>

<p>I ended up coding some prototypes that demonstrate the design concepts we came up with:</p>

<ul>
<li>The <a href="http://www.fleegix.org/demo/floss_usability_2007/proto_0.html">existing design</a>, for contrast.</li>
<li>A treatment using <a href="http://www.fleegix.org/demo/floss_usability_2007/proto_1.html">only standard formelements</a>, </li>
<li>A treatment <a href="http://www.fleegix.org/demo/floss_usability_2007/proto_2.html">using a custom icon</a> to indicate visiblity of the calendar layers</li>
</ul>

<p>Jeffrey Harris (who is essentially my equivalent on the Chandler Desktop application) and I put the feedback from the Sprint up on a <a href="http://chandlerproject.org/Notes/FlossSprint2007">wiki page on the Chandler wiki</a>. The design ideas and input were really great, and I'm looking forward to incorporating them into our design for the Web UI.</p>]]>
           </body>
           <title>
               <![CDATA[FLOSS Usability Sprint V]]>
           </title>
           <publishedAt>2007-11-12T20:18:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-11-12-floss-usability-sprint-v</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I've been doing a bit of work recently on the <a href="http://windmill.osafoundation.org/">Windmill</a> project for OSAF -- it's pretty usable already, and we're just now approaching the 0.2 release.</p>

<p>One of the pieces I added awhile back was an assert to check for broken images. After doing a bunch of poking around online, the one piece that seemed to elude everyone doing this kind of check was something that works in Safari 2. We plan to support Safari in Windmill, so I did a bit more research and hammered out something that seems to work reliably. </p>

<p>The crux of the problem with Safari is that it doesn't support the <code>complete</code></pre> attribute -- at least not for images loaded normally in markup. Interestingly though, it does support it for script-created images -- which opens to the door to this hack.</p>

<p>Here's the code:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">function</span> assertImageLoaded(img) {
  <span class="r">var</span> complete = img.complete;
  <span class="r">var</span> ret = <span class="pc">null</span>; <span class="c">// Return value</span>
  <span class="c">// Workaround for Safari -- it only supports the</span>
  <span class="c">// complete attrib on script-created images</span>
  <span class="r">if</span> (<span class="r">typeof</span> complete == <span class="s"><span class="dl">'</span><span class="k">undefined</span><span class="dl">'</span></span>) {
    <span class="r">var</span> test = <span class="r">new</span> Image();
    <span class="c">// If the original image was successfully loaded,</span>
    <span class="c">// src for new one should be pulled from cache</span>
    test.src = img.src;
    complete = test.complete;
  }
  <span class="c">// Check the complete attrib. Use strict equality</span>
  <span class="c">// check -- don't want undefined, null, etc.</span>
  <span class="c">// --------------------------</span>
  <span class="c">// False -- Img failed to load in IE/Safari, or is</span>
  <span class="c">// still trying to load in FF</span>
  <span class="r">if</span> (complete === <span class="pc">false</span>) {
    ret = <span class="pc">false</span>;
  }
  <span class="c">// True, but image has no size -- image failed to</span>
  <span class="c">// load in FF</span>
  <span class="r">else</span> <span class="r">if</span> (complete === <span class="pc">true</span> &amp;&amp;
    img.naturalWidth == <span class="i">0</span>) {
    ret = <span class="pc">false</span>;
  }
  <span class="c">// Otherwise all we can do is assume image loaded</span>
  <span class="r">else</span> {
    ret = <span class="pc">true</span>;
  }
  <span class="r">return</span> ret;
}</pre></div>
</div>

<p>The hack for Safari depends on the normal caching behavior of the browser.</p>

<p>When you do the check, the <code>complete</code></pre> attribute for the original image will be undefined -- but when you create a new Image with JavaScript, and set its <code>src</code></pre> to the <code>src</code></pre> of the original, it grabs the image from cache, and the <code>complete</code></pre> attribute for the script-created image is immediately set to true.</p>

<p>This assumes of course that Safari is pulling images from cache after the first hit, but that should be the default behavior, and in the vast majority of cases that's what you want. If you're using this code, and you get a bunch of false hits for broken images in Safari, you'll want to take a look at how both your browser and server are configured for caching.</p>]]>
           </body>
           <title>
               <![CDATA[Test for broken images -- works in Safari]]>
           </title>
           <publishedAt>2007-09-30T19:06:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-09-30-test-for-broken-images-works-in-safari</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Okay, now I'm a bit more inclined to believe the guys at Microsoft are serious about this stuff. <a href="http://www.microsoft.com/presspass/press/2007/sep07/09-04SilverlightPR.mspx">An MS press release has announced</a> they're working with the Mono guys to deliver Silverlight for Linux:</p>

<blockquote>
    <p>In addition, Microsoft will work with Novell Inc. to deliver Silverlight support for Linux, called Moonlight, and based on the project started on mono-project.com.</p>
</blockquote>

<p>Sure, like <a href="http://blogs.msdn.com/chkoenig/">Chris Koenig</a> pointed out to me when I asked about Linux support, Linux's desktop share is tiny. But there is a disproportionately high number of developers in that tiny share, and we're pretty vocal. :)</p>

<p>Working with Novell is an easy way to get going on this -- and the Linux support shows they're serious about competing with Adobe in this space.</p>]]>
           </body>
           <title>
               <![CDATA[MS to deliver Silverlight for Linux]]>
           </title>
           <publishedAt>2007-09-06T06:45:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-09-06-ms-to-deliver-silverlight-for-linux</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>BarCamp Houston 2 was great. The <a href="http://www.houstontech.org/">Houston Technology Center</a> was a really nice venue, and it was cool to hook up with so many locals who are into bleeding-edge tech. Nice too, to get some faces to go with Twitter avatar pics.</p>

<p>I was also pretty happy to see three other <a href="http://www.knowledgewire.com/">KnowledgeWire</a> alums representing -- <a href="http://twitter.com/mrshl">Marshall</a>, <a href="http://twitter.com/GerryM">Uncle Gerry</a>, and <a href="http://twitter.com/jonti">Jonti</a>.</p>

<p>Check out the <a href="http://blogs.chron.com/techblog/archives/2007/08/live_coverage_barcamp_houston_20_1.html">Twitter update archive</a> from Dwight Silverman (<a href="http://www.chron.com/">Houston Chronicle</a>).</p>

<p><strong>State of the Startup</strong></p>

<p>(Kurt Stoll, <a href="http://startuphouston.com/">StartupHouston.com</a>)</p>

<ul>
<li>Lots of startups in Houston, but little communication/coordination.</li>
<li>Not enough interested talent and not enough local capital. Houston startups have to go outside of town for their cash.</li>
<li>Brain drain -- not enough connection between the startup community and the universities, easy opportunities with big business in Houston.</li>
<li>Open-source participation can propel entrepreneurship</li>
</ul>

<p><strong>The Up Experience</strong></p>

<p>(Ernie Rapp, <a href="http://theupexperience.com/">The Up Experience</a>)</p>

<p>A conference modeled after TED (www.ted.com), coming in to Houston in February. One announced speaker is Steve Wozniak. </p>

<p>Seems a bit pricey at $1000, but they are trying to make it something pretty extraordinary.</p>

<p><strong>Spresent</strong></p>

<p>(Alexander Kouznetsov, <a href="http://www.spresent.com/">Spresent</a>)</p>

<p>Software-as-a-service, Web-based presentation application. Written in Flash. Looks pretty decent, if you need to do Powerpoint-style presentations.</p>

<p>If it were me, I probably wouldn't be able to get past my visceral distaste for Flash -- I'd use <a href="http://meyerweb.com/eric/tools/s5/">S5</a> or something. But I can see how it would really appeal to people who do presentations with a lot of media in them.</p>

<p><strong>OpenTeams</strong></p>

<p>(Tory Gattis, <a href="http://openteams.com/">OpenTeams</a>)</p>

<p>"Takes the icky out of wiki." These guys are a Houston-based startup.  </p>

<p>A friendly, more usable wiki-style collaboration Web-app for business. ZDNet blogs has a <a href="http://blogs.zdnet.com/Berlind/?p=573">good writeup</a> with video of the actual app.</p>

<p>Really nicely done Ajax frontend -- easy on the eyes, especially considering the amount of data that's getting packed in there. Their JavaScript toolkit weapon-of-choice is Dojo, and they use PHP/MySQL on the server. (I'm interested in talking to their font-end guy (he's in Austin) about their plans for transitioning to Dojo 1.0.)</p>

<p>I talked with Tory a little bit about open-source -- it's apparently a question they get asked a lot. He said they had tried to contribute some code to Dojo, but didn't have much luck coordinating with the Dojo guys to get it included.</p>

<p>They're an ASP, so they don't want to open-source the entire app. But I mentioned the idea that they could consider open-sourcing something smaller like a component -- something generally useful, but unique to their app. It's a nice way of contributing back without killing your whole business. Tory seemed interested in the idea, since people seem to be badgering them a lot about their open-source story.</p>

<p>I was also pretty impressed with the open way they've set up their business -- it's very community driven, and they're deliberately blurring the lines between employees and community. Check out their <a href="http://openteams.com/faq.html">FAQ on the Open Model Entrepreneurial Organization</a>.</p>

<p>I need to throw this out to the OSAF crowd, since it's completely free for non-profits. </p>

<p><strong>Text and Readability, E-Books</strong></p>

<p>Robert Nagle, <a href="http://www.imaginaryplanet.net/weblogs/idiotprogrammer/">IdiotProgrammer Weblog</a></p>

<p>Gerry Manacsa, <a href="http://www.wowio.com/">Wowio.com</a></p>

<p>(Disclaimer: I have a bunch of good friends at Wowio.) </p>

<p>Lots of talk about various types of new media, the importance of graphics versus text, and the influence on reading of technology.</p>

<p>I won a book for my answer to one of the poll questions. (The question: Where are some places people read? My answer: On the can.)</p>

<p>Robert has his slides <a href="http://www.slideshare.net/eschipul/sem-schipulevatt-barcamp-houston">available online here</a>.</p>

<p><strong>Silverlight</strong></p>

<p>Chris Koenig, <a href="http://www.microsoft.com/">Microsoft</a></p>

<p>A really impressive demo that showed how serious Microsoft finally has gotten about making RIA programming a first-class citizen in its tools-oriented programming ecosystem.</p>

<p>Silverlight is going to be an interesting technology to watch as it matures, and things like Ruby/Python support fall into place.</p>

<p>They tout it as cross-platform, but sadly, to the guys at MS that still just means "Wow, it works on Mac." I'll be impressed when there's a Linux player. No one expect development tools, but hey, Adobe has a Linux player for Flash. This is kind of minimum effort here, guys.</p>

<p>If Microsoft can lose billions of dollars on XBox, they can spend some resources on a Linux player for Silverlight. (And no, I don't want to hear what the Mono guys are doing.)</p>]]>
           </body>
           <title>
               <![CDATA[BarCamp Houston 2007]]>
           </title>
           <publishedAt>2007-08-29T06:00:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-08-29-barcamp-houston-2007</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I've been off for most of the past week as my mom had our boys (keeping all the grandkids together for the week, frighteningly enough), and my wife and I took the opportunity to do some house-hunting. We're looking for something with a bit more yard space for the boys to play in.</p>

<p>I've been offline a lot this week, but I did see an interesting post by Peter Michaux (creator of the <a href="http://forkjavascript.org/">Fork JavaScript library</a>), about <a href="http://peter.michaux.ca/article/3556">lazy function definition in JavaScript</a>.</p>

<p>This is a flavor of <a href="http://en.wikipedia.org/wiki/Self-modifying_code">self-modifying code</a> where on initial invocation a function actually redefines itself before executing and returning a value. On subsequent calls, it simply executes according to the updated definition. Peter's very simple first example looks like this:</p>

<pre><code>var foo = function() {
  var t = new Date();
  foo = function() {
    return t;
  };  
  return foo();
};
</code></pre></pre>

<p>Peter writes:</p>

<blockquote>
    <p>Another way of thinking about this this pattern is that the outer function that is first assigned to foo is a promise. It promises that the first time it is run it will redefine foo to a more useful function.</p>
</blockquote>

<p>The term 'promise' he uses is a reference to <a href="http://www.ibm.com/developerworks/linux/library/l-lazyprog.html">lazy evaluation in languages like Scheme</a>.</p>

<p>An obvious use for this pattern would be library code that paves over differences between browsers. (Peter's final example is a cross-browser function that gets the page scroll.) Having the function tailor itself for the specific browser allows you to avoid a conditional check for what browser every time the function is invoked.</p>

<p>This pattern might be a bit acrobatic for some people's taste -- it's arguably better to be clear than to be clever, particularly in code that lots of people will be touching. But it never hurts to have another powerful tool like this in the toolbox.</p>]]>
           </body>
           <title>
               <![CDATA[JavaScript lazy function definition]]>
           </title>
           <publishedAt>2007-08-18T18:59:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-08-18-javascript-lazy-function-definition</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>OSCON was great this year -- I'm really glad I was able to go, especially given all the added pressure of Chandler Server's end-of-release push. The content was decent, although I wouldn't say stellar. This time around I found a bit more value in meeting and talking to people.</p>

<p>The Sun party was excellent -- I had the enjoyable experience of getting to be the first person to tell Sun's <a href="http://blogs.sun.com/tmarble/">Tom Marble</a> about the new <a href="http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx">Microsoft Permissive License</a>. </p>

<p>The Mozilla party was decent, but the venue made it really difficult to hold a conversation, with the live music and the enclosed space.</p>

<p>I also had a good talk over dinner and beer with some of the guys from <a href="http://www.zimki.com/">Zimki</a>, those guys doing the interesting stuff with server-side JavaScript and utility computing. Their implementation of server-side JS has an interesting twist -- they use SpiderMonkey with mod_perl and Apache, rather than some flavor of Rhino/Java.</p>

<p><a href="http://bcm.vox.com/library/post/oscon-wrapup.html">BCM is right on the nose</a> -- one of the highlights for me too was ending up in the Doubletree hotel bar with the OSAF and <a href="http://www.metaweb.com/">Metaweb</a> crews and talking and joking about an enormous range of crap from hardcore tech stuff to bad TV. I also scored a nice <a href="http://www.freebase.com/">Freebase</a> T-shirt. (I was stoked to get a promo T-shirt -- especially after <a href="http://www.python.org/~guido/">Guido</a> was no help with that Google shirt.)</p>

<p>Crashing the O'Reilly speakers' party was pretty fun, and at the after-party at the Vault Martini Bar, I had a nice chat with <a href="http://www.slash7.com/">Amy Hoy</a> about UI design, Rails, and JavaScript -- topics that are near and dear to my heart.</p>

<p>Here are brief writeups of the talks that I attended. Most of this stuff is also posted over at the <a href="http://www.sitepoint.com/blogs/">SitePoint blogs</a>.</p>

<p><a href="http://www.sauria.com/blog/2007/08/03/oscon-2007/">Ted</a> and <a href="http://semanticmikeal.com/2007/08/oscon-2007.html">Mikeal</a> and <a href="http://t0asted.com/sblog/index.php?entry=entry070731-160243">Adam</a> have all posted writeups too.</p>

<p><strong>Managing Technical Debt</strong></p>

<p>Andy Lester is with the Perl Foundation, and maintains a blog at <a href="http://petdance.com/">petdance.com</a>.</p>

<p>Andy's talk gave practical advice for catching up on all the tasks you put off until some later date (that inevitably never comes) -- stuff like postponed docs, fixing broken tests (or just writing tests at all), backup regimes, TODOs in your code, etc.</p>

<p>He had a very simple and straightforward formula:</p>

<ul>
    <li>Identify your debts</li>
    <li>Determine the costs</li>
    <li>Pay the most profitable</li>
    <li>Stop incurring new debt</li>
    <li>Repeat as necessary</li>
</ul>

<p>The most important takeaway for me was the idea that you don't try to fix all your problems at once. You figure out what fix will give you the most bang for your buck -- not the easiest thing to fix, not the biggest problem. You fix whatever it's the <em>most profitable</em> to fix. </p>

<p>There was also a lot of good discussion during this talk on how to convince a manager to allow you to begin reducing technical debt with things like refactoring, increasing test coverage, adding documentation, or actually testing your disaster-recovery plan. The best advice was the idea of putting it in terms that the manager can understand (often with a manager either in money or time).</p>

<p>For example, if managers know that investing two days testing disaster recovery would save weeks of rebuilding critical infrastructure, or that spending a week refactoring crufty old code would make it 20% faster to implement new features, it's easier for them to justify the cost.</p>

<p>Andy has his slides <a href="http://petdance.com/perl/technical-debt/">available online here</a>.</p>

<p><strong>Open Design, Not by Committee</strong></p>

<p>Ted Leung is a Senior Engineer at OSAF, and blogs at <a href="http://www.sauria.com/blog">Ted Leung On The Air</a></p>

<p>Mimi Yin is a UI Designer at OSAF</p>

<p>(Disclaimer: I work at OSAF on the Web UI for Chandler Server.) This talk centered on the open design process used by OSAF in developing both the Chandler Desktop client, and the Chandler Server Web UI, and how open design differs from open development.</p>

<p>Open design is participatory, but mediated -- i.e., decisions are made within the context of community discussion and participation, but with a specific responsible party for decisions to avoid devolving into design-by-committee.</p>

<p>Specific topics included:</p>

<ul>
<li>The thought processes of developers versus designers -- developers think in terms of features and specs, designers think more holistically.</li>
<li>How to do design in a distributed, participatory environment -- use of tools such as wiki and mailing list.</li>
<li>How to judge the relative merits of design proposals based on specific goals, requirements -- i.e, use cases.</li>
<li>Defining the 'target user.'</li>
<li>How to build a community of contributors to the design process -- what is the equivalent of a 'commiter' in the open design process?</li>
</ul>

<p>The talk concluded by going over next steps for cultivating an open-design community -- by making objectives clear, getting people to use the apps and provide feedback, and providing ways for people to experiment with new designs.</p>

<p>Slides are <a href="http://conferences.oreillynet.com/presentations/os2007/os_leung.ppt">available online here</a>.</p>

<p><strong>The Holistic Programmer</strong></p>

<p>Adam Keys is a software developer and writer. His blog is at <a href="http://therealadam.com/">therealadam.com</a>.</p>

<p>The days of one guy putting together all the hardware and software together by himself in his garage are long gone -- working with computers increasingly means doing something very specialized in one of the layers between the hardware and the end-user. </p>

<p>Adam made a good case for the idea that despite this specialization people working with computers should develop at least a passing familiarity with the layers other than their own -- e.g., a guy working in the database learning typography, and a Web designer learning about compilers.</p>

<p>Many developers may not have the interest (or the discipline) to spend time learning about subjects so far removed from their little piece of the pie, but a couple of the benefits to doing so that Adam described seemed pretty compelling:</p>

<ul>
    <li>The ability to converse with the people you work with and understand better how your work interfaces with theirs.</li>
    <li>Gaining a new perspective that allows you to find unexpected or creative solutions to problems in your own domain.</li>
</ul>

<p>Adam spent the end of his talk going over the two example layers just mentioned -- CSS/layout/typography, and compilers. That might not have been something every developer was super-interested in learning about, but for a guy like myself who's kind of all over the place from the database layer all the way up to end-user-facing design, it was really interesting stuff.</p>

<p>Adam has his slides <a href="http://therealadam.com/presentations/oscon2007/HolisticProgrammer.pdf">available online here</a>.</p>

<p><strong>The Atom Publishing Protocol</strong></p>

<p>Joe Gregorio is a Senior Software Engineer at IBM</p>

<p>Overview of Atom Publishing (AtomPub), along with some of the gritty details and examples on how it dovetails with REST. Some of the highlights included:</p>

<ol>
<li>basic AtomPub document structure</li>
<li>CRUD operations</li>
<li>paging</li>
<li>How to handle non-text media like video/graphics/PDFs.</li>
</ol>

<p>Joe's slides are <a href="http://bitworking.org/projects/oscon2007/html/">available online here</a>.</p>

<p><strong>High Performance Web Pages</strong></p>

<p>Steve Souders is Chief Performance Yahoo at <a href="http://www.yahoo.com/">Yahoo</a>.</p>

<p>Talk focused on optimizing performance of client-side code, which -- surprisingly -- makes up 80-90% or more of the user wait time.</p>

<p>Steve ran quickly through 13 basic rules for high-performance Web sites:</p>

<ol>
<li>Make Fewer HTTP Requests</li>
<li>Use a Content Delivery Network</li>
<li>Add an Expires Header</li>
<li>Gzip Components</li>
<li>Put CSS at the Top</li>
<li>Move Scripts to the Bottom</li>
<li>Avoid CSS Expressions</li>
<li>Make JavaScript and CSS External</li>
<li>Reduce DNS Lookups</li>
<li>Minify JavaScript</li>
<li>Avoid Redirects</li>
<li>Remove Duplicate Scripts</li>
<li>Configure ETags</li>
</ol>

<p>Articles on techniques for all these rules are available online at <a href="http://developer.yahoo.com/performance/">Exceptional Performance</a> on the Yahoo Developer Network.</p>

<p>Steve also introduced the <a href="http://developer.yahoo.com/yslow/">YSlow</a> add-on for Firefox, that integrates with Firebug to analyze your pages according to the 13 rules and help you optimize your pages' performance.</p>

<p><strong>Windmill: Automated Testing of Your Ajax Web Applications</strong></p>

<p>Mikeal Rogers is a QA Development Engineer at the <a href="http://www.osafoundation.org/">Open Source Applications Foundation</a>, and has a blog at <a href="http://semanticmikeal.com/">semanticmikeal.com</a></p>

<p>Adam Christian is also a QA Development Engineer at the <a href="http://www.osafoundation.org/">Open Source Applications Foundation</a>. His blog is at <a href="http://t0asted.com/">t0asted.com</a></p>

<p>(Disclaimer: I work at OSAF and am a committer on the <a href="http://windmill.osafoundation.org/">Windmill</a> project.) This talk started with Adam showing a brief demonstration of using <a href="http://windmill.osafoundation.org/">Windmill</a> to test the Ajax Web UI for OSAF's <a href="http://chandlerproject.org/">Chandler Server</a>, including drag/drop testing of the calendar view.</p>

<p>The talk continued with Mikeal describing the reason for building a brand-new framework rather than using an existing tool like Selenium -- frustration with the inability debug broken tests. Windmill is designed to allow tests to be paused and debugged interactively.</p>

<p>They followed with a brief overview of Windmill's Python/JavaScript architecture, and ended with a demonstration of the cross-browser recorder that can be used to create tests from the Windmill IDE without writing code.</p>

<p>Mikeal and Adam have their slides available <a href="http://windmill.osafoundation.org/trac/attachment/wiki/Miscellaneous/OSCON2007-Windmill.pdf">online here</a>.</p>

<p>They have some screenshots and screencasts available <a href="http://windmill.osafoundation.org/trac/wiki/ScreenshotsAndScreencasts">online here</a>.</p>

<p><strong>People Hacks</strong></p>

<p>Adam Keys is a software developer and writer. His blog is at <a href="http://therealadam.com/">therealadam.com</a>.</p>

<p>In this talk, Adam presented a number of methods for effective advocacy and for getting along with other developers. In other words, interacting with people is as important as interacting with hardware or software. Problems in this sphere have no technical solution -- they require a social one. Thus, the idea of 'people hacking.'</p>

<p>People hacking is not rooted in nefarious black-hat hacking, but simply in using tools of social jujutsu (sometimes on yourself, even) to gain traction for ideas you're trying to advocate. Paying more attention to the people side of things can help you build the kind of integrated, smoothly functioning team capable of executing (to borrow a basketball metaphor) the "no-look pass."</p>

<p>A few sample ideas included:</p>

<ul>
    <li>Simply smiling -- makes yourself and people around you feel more positive</li>
    <li>Avoid negativity -- try the ABBA Method (see the slides for details)</li>
    <li>Avoid criticism</li>
    <li>Compliment before criticizing</li>
</ul>

<p>Some ideas followed about how to deal with jerks in your organization, including the simple-but-effective "No Asshole Rule" (from the book of the same name) that encourages a zero-tolerance toward asshole behavior in your group -- even from so-called superstar programmers.</p>

<p>Adam also encouraged a little self-evaluation to determine if your yourself may be a recovering jerk, and that by focusing on improving your ability to working well with those around you, you can also reform yourself.</p>

<p>Adam has his slides <a href="http://therealadam.com/presentations/oscon2007/PeopleHacks.pdf">available online here</a>.</p>

<p><strong>Adventures in Localization</strong></p>

<p>Wil Clouser is a Web Developer with the <a href="http://www.mozilla.com/">Mozilla Corporation</a>, and blogs at <a href="http://micropipes.com/blog/">Micropipes::Blog</a>. Mike Morgan is Manager of Web Development at <a href="http://www.mozilla.com/">Mozilla Corporation</a>, and has a blog at <a href="http://morgamic.com/">morgamic.com</a>.</p>

<p>This talk described the process of internationalizing Web properties at Mozilla, specifically <a href="http://www.mozilla.com/">mozilla.com</a> and <a href="http://addons.mozilla.org/">addons.mozilla.org</a>, site which together receive almost 200 million hits a day. The localization process for the Web sites is still behind the Firefox client, which ships with over 40 different locales.</p>

<p>They started by discussing a few of the pitfalls of localization, such as pluralization and noun-gender, and then went on to talk about the system they settled on for localizing the Mozilla Web properties, which are a combination of static text in templates and dynamic content pulled from a database.</p>

<p>For static text, they ended up using GNU's <a href="http://www.gnu.org/software/gettext/">GetText</a>, as it's a stable, well-proven solution already in wide use. It has good documentation, pluralization support, and a wide variety of tools that translators may already be familiar with.</p>

<p>For the dynamic content, they used a simple database-driven solution of lookups based on string ID and locale key. (They initially looked at <a href="http://pear.php.net/package/Translation2/">PEAR::Translation2</a>, but it turned out not to be flexible enough for their purposes.) The advantages of this system are its simplicity, and the fact that it's easy to apply to dynamic content lookup anywhere in the database. Drawbacks are the large table sizes and complicated joins required to get data out in a way that allows language fallback.</p>

<p>They also touched on some of the improved localization tools that are in develoopment, such as Canonical's <a href="https://launchpad.net/">Launchpad</a>, and various ways of getting the community involved and empowered to help out with localization.</p>

<p>Slides for their presentation are available <a href="http://people.mozilla.com/~morgamic/presentation.pdf">online here</a>.</p>

<p>Wil also has a follow-up blog post called <a href="http://micropipes.com/blog/2007/07/26/ten-tips-for-website-localization/">Ten Tips for Website Localization</a>.</p>

<p><strong>The Continual Opening of Second Life</strong></p>

<p>Rob Lanphier, (Rob Linden) is Open Source Busybody at <a href="http://www.lindenlabs.com/">Linden Labs</a></p>

<p>Aaron Brashears (Phoenix Linden) works at <a href="http://www.lindenlabs.com/">Linden Labs</a></p>

<p>This was a fairly free-form discussion that started with Rob asking everyone what particular facets of Second Life attendees were interested in.</p>

<p>The proceeded with a general introduction of SL, with an accompanying background demonstration of the SL client, including a tour of virtual workspaces, demos of the new integrated voice-chat client, and harrassement of random Linden Labs employees in-world.</p>

<p>Aaron talked a lot about the evolution of the current system architecture, and talked about the roadmap toward the more distributed architecture that open-sourcing the server-side would require -- a system that would allow participation in the Grid by non-Linden servers.</p>]]>
           </body>
           <title>
               <![CDATA[OSCON 2007]]>
           </title>
           <publishedAt>2007-08-07T00:15:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-08-07-oscon-2007</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I recently fixed an IE-only bug in Chandler Server that resulted from moving the base listener for some event delegation code from the body to another node lower down in the DOM tree.</p>

<p>Interesting that I've never tripped over this before, because it's so totally glaring -- but in IE (both IE6 and IE7), absolute-positioned block elements that have no background set (i.e., no <code>background</code></pre>, <code>background-color</code></pre>, or <code>background-image</code></pre>) do not trigger click or mousedown DOM events.</p>

<p>I haven't done any extensive testing to see what all is out of whack there, but I do have a <a href="/demo/ie_bg_onclick.html">minimal test page</a> that shows the basic behavior in action. </p>

<p>If you happen to have a VM already running and IE fired up, go take a look. The div on the left has no background-color specified. The one on the right does. Otherwise they're identical. Click on the left one, you get bupkis. Click on the right one, you get a JS alert box.</p>

<p>Setting the the background value to transparent has the same effect. (Or non-effect, should I say?)</p>

<p>I'm belaboring the obvious but if IE were an open-source project, I'd go to their bug tracker and look to see if someone else has already reported this. As it is, the public bug database for IE7 is <a href="https://connect.microsoft.com/site/sitehome.aspx?SiteID=136">'temporarily closed,'</a>. For whatever value of 'temporarily.'</p>

<p>The IE guys have done a lot of stuff right -- turning off their public bug database is not one of them.</p>]]>
           </body>
           <title>
               <![CDATA[IE background CSS and onclick/onmousedown]]>
           </title>
           <publishedAt>2007-08-04T06:36:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-08-04-ie-background-css-and-onclick-onmousedown</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>First John Lam <a href="http://www.iunknown.com/2007/07/a-first-look-at.html">announces Iron Ruby</a>, to be released under something called the <a href="http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx">Microsoft Permissive Licesnse</a>. It's basically a rebranded <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache license</a> -- and honestly, seeing that stuff on a Web page with an MS logo had me envisioning some alternate-reality Steve Ballmer with a full head of hair. (Remember that episode of classic Trek where Spock has a Fu-Manchu-style goatee?)</p>

<p>The <a href="http://developer.yahoo.com/performance/">perf guys over at Yahoo</a> dropped <a href="http://developer.yahoo.com/yslow/">YSlow</a> on us, which should help us be even more disgusted at how long we're making our users wait for crap to load.</p>

<p>Brendan over at Mozilla piled on by announcing a <a href="http://weblogs.mozillazine.org/roadmap/archives/2007/07/new_projects.html">slew of fun new stuff</a> -- it's an um, barrel full of new monkey-projects (sorry, couldn't help myself) over at Mozilla: <a href="http://wiki.mozilla.org/JavaScript:ActionMonkey">ActionMonkey</a>, bringing all the Adobe-donated Tamarin-goodness into the JS engine for Mozilla 2, <a href="http://wiki.mozilla.org/Tamarin:IronMonkey">IronMonkey</a>, making use of the above-mentioned Permissive License code to make Tamarin multi-lingual (Ruby in the browser, anyone?), and <a href="http://wiki.mozilla.org/Tamarin:ScreamingMonkey">ScreamingMonkey</a>, a project to bring Tamarin to other browsers such as IE. Holy crap, that's a lot of what it is, all in one announcement. </p>

<p>Good stuff. Looking forward to seeing how all these projects progress.</p>]]>
           </body>
           <title>
               <![CDATA[2007 OSCON-season announcement bonanza]]>
           </title>
           <publishedAt>2007-08-04T05:42:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-08-04-2007-oscon-season-announcement-bonanza</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>A common hack you see with both Ruby/Rails and PHP is the use of brackets in form element names (e.g., <code>name="foo[bar]"</code></pre>) to 'namespace' the form -- when values submitted from elements like this reach the server, they are converted into properties on an object.</p>

<p>Up to now, the <a href="http://js.fleegix.org/ref#fleegix.form.toHash"><code>toHash</code></pre></a> method in the fleegix.form module didn't do anything special form elements named using that hack. </p>

<p>This method converts form elements into a keyword/value JavaScript object. It does correctly stick the values for things like sets of checkboxes or a multi-select into an array, like you'd expect -- but it didn't do anything special with element names with brackets.</p>

<p>So, an element with <code>name="zardoz[zed]"</code></pre> would end up in the converted object looking like <code>convertedForm['zardoz[zed]']</code></pre>. Not really easy on the eyes, and probably not the intent when someone sets up those bracketed form-element names.</p>

<p>This past week <a href="http://www.kjfx.net/">Kevin Faulhaber</a> was kind enough to pass along a <code>toHash</code></pre> patch that converts those properly. So <code>name="zardoz[consuela]"</code></pre> comes out correctly in the converted object as <code>convertedForm['zardoz']['consuela']</code></pre> -- or, since you don't have those gnarly brackets in the actual keyword, you can use normal dot-syntax -- <code>convertedForm.zardoz.consuela</code></pre>.</p>

<p>Since <code>toHash</code></pre> is the backbone of both the <a href="http://js.fleegix.org/ref#fleegix.form.serialize"><code>serialize</code></pre></a> and <a href="http://js.fleegix.org/ref#fleegix.form.diff"><code>diff</code></pre></a> methods in the form module, it wasn't practical to make this the default behavior. So, to get this new behavior, just pass a second argument to the <code>toHash</code></pre> method -- an options object, with the <code>hierarchical</code></pre> property set to <code>true</code></pre>:</p>

<pre><code>var obj = fleegix.form.toHash(someForm, 
  { hierarchical: true });
</code></pre></pre>

<p>Easy as pie. </p>

<p>I'm thinking now it would also be interesting to see if we could handle names with empty brackets (<code>name="foo[]"</code></pre>) like the PHP guys use to create arrays on the server. </p>

<p>This change is in the <a href="http://svn.fleegix.org/fleegix_js/trunk/">Fleegix.js trunk</a>, and will be making it into the next release. For info on the other interesting stuff you can do with forms using Fleegix.js, check out the <a href="http://js.fleegix.org/ref#fleegix.form">form module documentation</a>.</p>]]>
           </body>
           <title>
               <![CDATA[Hierarchical forms with fleegix.form]]>
           </title>
           <publishedAt>2007-07-12T07:14:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-07-12-hierarchical-forms-with-fleegix-form</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Man, I've really been buried in work and family stuff -- I totally missed this bit of news. </p>

<p>Apparently when Steve Yegge couldn't convince the good folks at Google to start using Ruby and Rails, <a href="http://steve-yegge.blogspot.com/2007/06/rhino-on-rails.html">he decided to do a JavaScript clone of it</a>, taking advantage of JS's status as one of Google's officially sanctioned languages.</p>

<p>According to this older <a href="http://www.iunknown.com/2007/06/steve-yegge-por.html">post by John Lam</a>:</p>

<blockquote>
    <p>Steve decided to do what any other frustrated programmer would do: he ported Rails to JavaScript. Line by line. In 6 months. Working 2000 hours.</p>
</blockquote>

<p>I'll look forward to taking this thing for a test drive if and when it becomes something publicly available.</p>]]>
           </body>
           <title>
               <![CDATA[Steve Yegge's JavaScript port of Rails]]>
           </title>
           <publishedAt>2007-07-05T05:30:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-07-05-steve-yegges-javascript-port-of-rails</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Looks like <a href="http://support.microsoft.com/kb/933566/">security update MS07-033</a> includes <a href="http://support.microsoft.com/kb/929874/">GDR fix 929874 for JScript memory leaks in IE6 on Windows XP</a>. The description seems to indicate that the fix is good for memleaks of both the circular-reference and closure variety.</p>

<p>There are of course a lot of people taking the "cold, dead fingers" approach with IE6, so this is great news for us on the Cosmo team, and for anyone developing large-scale Ajax apps. Kudos to the guys on the IE team for doing something right.</p>]]>
           </body>
           <title>
               <![CDATA[JavaScript memory leaks fixed in IE6 on Windows XP]]>
           </title>
           <publishedAt>2007-06-24T21:24:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-06-24-javascript-memory-leaks-fixed-in-ie6-on-windows-xp</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Took a bit of time this afternoon and put together all the recent fixes and improvements to Fleegix.js into a release, <a href="http://downloads.fleegix.org/fleegix.js/releases/fleegix-0.3.2/">version 0.3.2</a>.</p>

<p>There are a bunch of miscellaneous goodies in there -- a couple of handy utility functions in the new fleegix.dom and fleegix.css modules, some nice eye-candy additions in the fleegix.fx library, and some improvements to the API reference. (Thank you, Kev!)</p>

<p>Other fixes -- the fleegix.event system now works properly across iframe borders in IE, and I've added in stopPropagation and preventDefault. Also fixed a nice null-vs.-undefined bug in form.toHash. Thanks muchly to the <a href="http://windmill.osafoundation.org/">Windmill</a> guys for making stuff break.</p>

<p>The whole library is still 'bodaciously small,' weighing in at 24KB for the <a href="http://downloads.fleegix.org/fleegix.js/releases/fleegix-0.3.2/fleegix.js">compressed file</a>, and 50KB for the <a href="http://downloads.fleegix.org/fleegix.js/releases/fleegix-0.3.2/fleegix.js.uncompressed.js">uncompressed one</a>.</p>

<p>As usual you can grab the latest build or SVN source off the <a href="http://js.fleegix.org/download">Fleegix.js download page</a>.</p>]]>
           </body>
           <title>
               <![CDATA[Fleegix.js 0.3.2 release]]>
           </title>
           <publishedAt>2007-05-20T22:39:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-05-20-fleegix-js-0-3-2-release</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I just got back from two weeks out in San Francisco at the OSAF offices. It was a great trip, and as always I really enjoyed the wonderful OSAF hospitality -- something that I always try my best not to take for granted. </p>

<p>This time around, with the exception of a couple of nights in a hotel, I crashed at <a href="http://t0asted.com/sblog/">Adam's</a> place. That was great fun, although it was a bit of work trying to keep up with those younger dudes. :) Just don't have the stamina I used to have. We drank a decent quantity of beer, and I got my feet wet with Python and Django.</p>

<p>Now I'm back here in Houston, trying to work through the inevitable pile of stuff that accumulates while you're gone -- but I figured I'd take a quick sec to respond to <a href="http://semanticmikeal.com/2007/03/tag-game-firefox-addones-i-couldnt-live.html">Mikeal's tag</a>. The topic is "Firefox add-ons you can't live without." Here are mine:</p>

<ol>
<li>Firebug  -- I'm a Web UI developer, 'nuff said.</li>
<li>Adblock -- Makes browsing the Web bearable. Even Yahoo doesn't induce seizures anymore.</li>
<li>Web Developer -- See number 1, above.</li>
<li>Foxmarks -- This add-on actually got me using bookmarks again. (As an aside, I used it at my wife's family's place in Japan, and the localized Japanese-language install was perfect.)</li>
<li>Sage -- I have fairly modest feed-reader needs, so I love that it just uses my bookmarks, and that I can use a custom stylesheet.</li>
</ol>

<p>That's the lot. I'm scratching my head trying to figure out who to tag here -- I guess it might be cool to tag <a href="http://lullabiesincode.blogspot.com/">Travis</a> with the "Firefox add-ons" question. Maybe that will give him a reason to get off his sorry ass and make a blog post. :)</p>]]>
           </body>
           <title>
               <![CDATA[Back from San Fran, and tag, I'm 'it' -- Firefox add-ons]]>
           </title>
           <publishedAt>2007-04-29T19:18:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-04-29-back-from-san-fran-and-tag-im-it-firefox-add-ons</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Working at OSAF, I am surrounded by a bunch of uber-Pythonistas, I'm pretty comfortable doing most server-side or scripting tasks in Ruby, but ever since I started work there, I've been wanting to give Python a go.</p>

<p>So, the other night I decided to pull the trigger, and being a Web guy, playing with a Web-dev framework like Django seemed like a decent way to get started. I took a bit of time setting up the latest Django release, 0.96, on my laptop, which runs an upgraded Ubuntu Edgy with a hand-rolled Python 2.5. </p>

<p>I did have some issues trying to get Django talking to the database (PostgreSQL version 8.2), because of version-differences in the psycopg2 database connector. (I was trying to use an apparently unsupported beta release.)</p>

<p>Now I've got it happily talking to Postgres, running under Apache/mod_python, and I'm slowly working my way through the tutorial. Right now I'm playing around with models, and trying to map that mentally to what I want the end result to look like in the DB. </p>

<p>Django looks pretty nice. It seems fairly similar to Rails in a lot of respects so far -- and of course Python is super-clean and readable, which makes stuff very easy to follow. </p>]]>
           </body>
           <title>
               <![CDATA[Down the Python path with Django]]>
           </title>
           <publishedAt>2007-04-22T18:58:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-04-22-down-the-python-path-with-django</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Awhile back I took a bit of a break from blog posts, and created a <a href="http://js.fleegix.org/">Web site for Fleegix.js</a>. Fleegix.js a lightweight, cross-browser set of JavaScript libraries for building dynamic Web-app UIs. From the Web site:</p>

<blockquote>
    <p>Fleegix.js includes a concise but powerful events system, an industrial-strength XHR library, a simple, no-muss-no-fuss XML parser, and some handy tools for working with Web forms, as well as other basic tools you need to build an Ajaxey Web UI.</p>
</blockquote>

<p>It comprises code I've been using in personal projects for quite awhile now, as well as updated versions of some of the code that was included in my Ajax book. The current release is <a href="http://downloads.fleegix.org/fleegix.js/releases/fleegix-0.3.1/fleegix.js">version 0.3.1</a>.</p>

<p>The impetus for building the site was at least in part what PPK of QuirksBlog referred to in a post back in February as <a href="http://www.quirksmode.org/blog/archives/2007/02/sxsw_and_the_fu.html">"regaining [his] sense of fun."</a> It's been years since I built a site from scratch, and I had the urge to pull up Photoshop and play with some design.</p>

<p>It ended up being really fun doing an over-the-top take on the stereotypical Web 2.0 site -- with the in-your-face gradients everywhere, and the big honking badge thing at the top. It was also a great opportunity to go a bit more in depth into CSS, and approach it from a different angle.</p>

<p>Okay, sure, the Web needs another JavaScript toolkit like a hole in the head, but the code is there, and I enjoy working with it. So if it provides some utility for somebody out there besides me, I'm a happy man.</p>]]>
           </body>
           <title>
               <![CDATA[Fleegix.js, a lightweight JavaScript toolkit]]>
           </title>
           <publishedAt>2007-04-11T01:16:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-04-11-fleegix-js-a-lightweight-javascript-toolkit</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Fortify Security's recent paper on <a href="http://www.fortifysoftware.com/servlet/downloads/public/JavaScript_Hijacking.pdf">JavaScript Hijacking (PDF)</a> has stirred up a lot of interest online around the subject of JavaScript/JSON security. Some of the articles are a bit alarmist, but it is a vulnerability worth understanding a bit better.</p>

<p>It's based on techniques similar to Jeremiah Grossman's original <a href="http://jeremiahgrossman.blogspot.com/2007/01/gmail-xsrf-json-call-back-hackery.html">GMail contact-list hack</a>. (The <a href="http://events.ccc.de/congress/2006/Fahrplan/attachments/1158-Subverting_Ajax.pdf">Subverting Ajax</a> paper by Stefano Di Paola and Giorgio Fedon also uses prototype hijacking, but has some seemingly exotic prerequisites like "a forward proxy and browser vulnerable to HTTP Response Splitting/Smuggling." See Grossman's <a href="http://jeremiahgrossman.blogspot.com/2007/01/review-of-subverting-ajax-white-paper.html">deconstruction of the paper here</a>.)</p>

<p>The vulnerability described in this new paper (and indeed many of the security issues with Ajax) comes from a confluence of three things:</p>

<ol>
<li><strong>JSON</strong>: It's not just a data format, it can also be executable code.</li>
<li><strong>Remote scripting</strong>: Allows you to get around the browser's same-origin security policy, resulting in some other site's JavaScript-code chocolate in your page's execution-context peanut butter. (Sure, it's a hokey metaphor, but you get the idea.)</li>
<li><strong>JavaScript</strong>: Everything's mutable, so if you can get someone else's code to run in your page, you have all kinds of opportunities to coax stuff out of it.</li>
</ol>

<p>There's no point in going into a lot of detail here -- Joe Walker (of the <a href="http://getahead.org/dwr">DWR</a> Ajax library) has <a href="http://getahead.org/blog/joe/2007/04/04/how_to_protect_a_json_or_javascript_service.html">an excellent blog post on this</a> with some good background linkage, and explanation of some different things you can do to protect your JSON service. But the bottom line is this -- don't serve out executable JavaScript code (JSON or otherwise) with cookies-only auth over GET.</p>

<p>(And for the people who are still hyperventillating over the prospect of being hakz0r3d in horrible ways by their Ajaxy Web UIs, I would also suggest giving Grossman's <a href="http://www.whitehatsec.com/home/resources/articles/files/myth_busting_ajax_insecurity.html">"Myth-Busting AJAX (In)security"</a> article a read.)</p>

<p>Actually I think the thing that sticks out most to me on reading the JavaScript Hijacking paper is the assumption that it is incumbent on the JavaScript toolkits to protect their users (the developers, that is) from this particular problem:</p>

<blockquote>
    <p>We determined that among them only DWR 2.0 implements mechanisms for preventing JavaScript Hijacking. The rest of the frameworks do not explicitly provide any protection and do not mention any security concerns in their documentation.</p>
</blockquote>

<p>I understand that a lot of people use these libraries precisely because they don't have a lot of expertise in JavaScript or Ajax-style development, but I'm still kind of dubious. I can sure see expecting a mention of these kinds of issues in the docs, but the pure client-side fixes are fairly heavy-handed and intrusive.</p>

<p>As a side note, if you're interesting in playing around with this vulnerability, the authors of the paper used the deprecated <code>setter</code></pre> syntax for the code that does the actual dirty work of filching the private data in the example. A better way to do it is with the <a href="http://developer.mozilla.org/en/docs/index.php?title=Core_JavaScript_1.5_Guide:Creating_New_Objects:Defining_Getters_and_Setters&amp;printable=yes"><code>__defineSetter__</code></pre></a> method.</p>]]>
           </body>
           <title>
               <![CDATA[JSON, JavaScript, and CSRF security holes]]>
           </title>
           <publishedAt>2007-04-05T04:57:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-04-05-json-javascript-and-csrf-security-holes</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I got an e-mail this past week with an interesting question from a guy who was reading my Ajax book:</p>

<blockquote>
    <p>why you do the check for 'Msxml2.XMLHTTP' instead of 'Msxml2.XMLHTTP.6.0' which is apparently the latest release from Microsoft that has numerous improvements?</p>
</blockquote>

<p>Naturally, I had an incredibly well-throught-out rationale for it -- "because that's how I originally did it, and it works." I had seen examples in the wild of using different specific program IDs (i.e., versions of the MSXML library) to get an XMLHttpRequest object, but never gave it much thought since my own code manifestly was working without.</p>

<p>Sure, "does it actually work" is the acid test -- no one cares how superbly designed your API is if they can't use your frigging app. But still, it's good to have someone ask these kinds of questions, so after the initial "ummm ..." reaction, you can get yourself educated. Otherwise it's all just <a href="http://en.wikipedia.org/wiki/Cargo_cult_programming">cargo cult programming</a>.</p>

<p>His initial e-mail kicked off a bit of discussion, and in the back-and-forth, there were some interesting links unearthed.</p>

<ul>
<li>An unintentionally funny exchange where Eric Pascarello ("Ajax in Action," Manning) <a href="http://forums.asp.net/1622845/ShowThread.aspx">tries his damndest to help with an MSXML question</a>, but seems to be totally misunderstanding what the guy is asking.</li>
<li>A fairly succinct explanation of <a href="http://www.faqts.com/knowledge_base/view.phtml/aid/35742">why you don't need to get too torqued up</a> about which specific version of MSXML you're using.</li>
<li>The guys at BrainJar go to 11 (okay, it's actually going to 7.0, whatever) <a href="http://www.brainjar.com/dhtml/ajax/">checking for all possible progIDs</a>.</li>
</ul>

<p>The bottom line, according to <a href="http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx">this post the Microsoft XML Team's Weblog</a>, is that you should try to use MSXML 6.0 if you can, and if it's not available, you should fall back to MSXML 3.0:</p>

<blockquote>
    <p>Use MSXML 6.0 - it is "in the box" on Vista and available for download on Win2k, XP, and 2003.  It has the best security, performance, reliability, and W3C conformance</p>
    
    <p>MSXML 3.0 is our preferred "fallback" -- It is installed on every OS from a fully patched Win2k SP4 installation on up, so it requires "zero-deployment" and is serviced regularly with the OS</p>
</blockquote>

<p>You can read for yourself what they say about the other version numbers on the blog post, but they don't recommend using them.</p>

<p>Using no program ID at all (e.g., <code>new ActiveXObject('Msxml2.XMLHTTP')</code></pre>) will give you version 3.0. (From the blog post: "The version-independent ProgID is always bound to MSXML 3.") That's why it's no real sweat to be invoking the XMLHttpRequest object with no progID -- you get MS's preferred fallback anyway, so it works just fine. You just don't get the most up-to-date kung fu.</p>

<p>I've updated the XHR library for <a href="http://js.fleegix.org/">Fleegix.js</a> to take this new info into account. That change, and a bunch of bugfixes make this newest one <a href="http://downloads.fleegix.org/fleegix_js/releases/fleegix-0.3.1.tar.gz">version 0.3.1</a>.</p>]]>
           </body>
           <title>
               <![CDATA[MSXML versions and XMLHttpRequest]]>
           </title>
           <publishedAt>2007-04-04T05:32:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-04-04-msxml-versions-and-xmlhttprequest</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>While I was in Japan, I had reasonable computer access, and did manage to a bit to <a href="http://twitter.com/mde">my Twitter account</a>. The short format has a lot less overhead than a whole blog post, but still scratches the posting itch.</p>

<p>Since I got to do a lot of the traditional Japanese things while I was there, I went back and pulled the URLs for the Wikipedia links I stuck in my Twitter posts. It's an interesting set of link-artifacts from the trip. Here's the list:</p>

<ul>
<li><a href="http://en.wikipedia.org/wiki/Shochu">shochu</a></li>
<li><a href="http://en.wikipedia.org/wiki/Kumamoto">Kumamoto</a></li>
<li><a href="http://en.wikipedia.org/wiki/Takamisakari">Takamisakari</a> (Also a <a href="http://youtube.com/watch?v=_zUJYlz_UjA">YouTube clip here</a>, the dude's a real character)</li>
<li><a href="http://en.wikipedia.org/wiki/Sento">sento</a></li>
<li><a href="http://en.wikipedia.org/wiki/Shichi_Go_San">Shichi-Go-San</a></li>
<li><a href="http://en.wikipedia.org/wiki/Enka">enka</a></li>
<li><a href="http://en.wikipedia.org/wiki/Doraemon">Doraemon</a></li>
<li><a href="http://en.wikipedia.org/wiki/Natto">natto</a></li>
<li><a href="http://en.wikipedia.org/wiki/Umeboshi">umeboshi</a></li>
<li><a href="http://en.wikipedia.org/wiki/Ueno_Zoo">Ueno Zoo</a></li>
<li><a href="http://en.wikipedia.org/wiki/Izakaya">izakaya</a></li>
<li><a href="http://en.wikipedia.org/wiki/Kaiten_zushi">kaiten-zushi</a></li>
</ul>

<p>We had some camera issues, but we did manage to get a few photos. About a dozen or so are <a href="http://www.flickr.com/photos/fleegix/sets/72157600035830338/">up on Flickr</a>.</p>]]>
           </body>
           <title>
               <![CDATA[Back from Japan, list o' links]]>
           </title>
           <publishedAt>2007-03-30T17:25:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-03-30-back-from-japan-list-o-links</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I'm off to Japan for two weeks. Wish it were for something fun, but it's for my father-in-law's funeral. It will of course be nice to see Japan -- I haven't been back there since 2000, and I miss it a lot sometimes. It'll be interesting to see how stuff has changed.</p>

<p>I imagine my online time will be fairly limited, so posting will be sparse or non-existent while I'm gone.</p>]]>
           </body>
           <title>
               <![CDATA[Heading to Japan]]>
           </title>
           <publishedAt>2007-03-12T04:12:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-03-12-heading-to-japan</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>"This is like deja-vu all over again" was the famous quote from Yogi Berra. There's something unpleasantly familiar about the latest set of royalty rates for Webcast radio just announced by the Copyright Royalty Board. We did pretty much this same thing back in the fall of 2002 -- it stunk to high heaven then, and it looks like an even bigger pile of crap now.</p>

<p>Bill Goldsmith, who runs <a href="http://www.radioparadise.com/">Radio Paradise</a>, has a <a href="http://www.kurthanson.com/archive/news/030207/index.shtml">blog post on it</a>, and Kurt Hanson has the rate breakdown <a href="http://www.kurthanson.com/archive/news/030207/index.shtml">nicely represented in a graphic</a> over at his Radio and Internet Newsletter.</p>

<p>Basically the way it works is this -- the record companies feel like they got screwed on the broadcast radio thing, so they've managed to finagle a 'per-performance' royalty requirement for digital broadcast of songs. So even after you've coughed up your <strike>protection money</strike> royaties to BMI, ASCAP, SESAC, or whomever, for the tracks in your playlist, you still have to pay a <em>per-play, per-listener</em> 'performance royalty' to <a href="http://www.soundexchange.com/">SoundExchange</a>.</p>

<p>This means that a hobbyist Webcaster is expected to pay a royalty fee each time an individual listener hears a particular track, but a mega-corporation like Clear Channel pays zilch per-performance to broadcast the same song.</p>

<p>To add insult to injury here, Congress has given the RIAA a free pass -- a 'monopoly exception' -- to negotiate on the behalf of <em>all</em> artists who produce music. So even if artists don't want the record company goons 'negotiating' ("That's a real nice Internet radio stream you have there. It'd be a shame if something happened to it.") for them, there's no established, obvious way to opt out.</p>

<p>The system does still allow for artists to negotiate specific agreements of their own on a case-by-case basis. (Having the freedom to negotiate a contract with whomever you want is one of those pesky free-market fundamentals that must drive those record-label dudes completely up a tree.) </p>

<p>So when this royalty shit first hit the fan back in '02 -- rather than paying these silly people at SoundExchange actual cash to stream the downtempo electronica groove tracks on my not-for-profit Webcast radio station, <a href="http://www.epiphanyradio/">EpiphanyRadio</a>, I decided I'd actually try going the 'royalty-free wavier' route. </p>

<p>In October of 2002, I threw out the entire playlist and started over from scratch. Since then, each and every track is streamed with the explicit permission of the artist, with an understanding that I pay absolutely no royalties of any kind -- not to BMI, ASCAP, SESAC, and certainly not the laughable 'performance royalties' the RIAA has managed to scam out of a compliant Congress. (I should add that we also stream tracks from Netlabels like <a href="http://www.mono211.com/">Monotonik</a> or <a href="http://www.kahvi.org/">Kahvi Collective</a> who explicitly state on their site that the music is freely distributable as long as you're not selling it.) </p>

<p>I get stuff in e-mail, CDs come in the mail to my house -- I pay no royalty fees, and the artists and labels get free promotion for their music.</p>

<p>These new royalty fees are interesting, because the first go-round with all this drove me to try the all-indie, 100% RIAA-free format -- with far more success that I initially anticipated. Now it seems they want to squeeze the poor hobbyists even more. My guess is that the short-term effect will be a lot of small streams going under. But the longer-term effect may be to push people even further from mainstream music, at least online -- people have had Webcast radio long enough that they're not going to go back to the lowest-common-denominator crap shoveled at them on FM radio. </p>

<p>Seeing this happening again now -- with an even more outrageous fee schedule -- makes me doubly happy that I've already opted out of that horrible, corrupt system. It turned out to be a beautiful thing, because some of these indie guys are amazing, creative geniuses, and have something really worthy of being heard. Now the stream has a really sweet playlist -- and it's all completely immune to the predations of despicable thugs like the RIAA and their ilk.</p>

<p>Maybe some other Webcast radio stations will take this change as an opportunity to follow suit, and angle toward indie music and direct communication with the artists. </p>]]>
           </body>
           <title>
               <![CDATA[Here we go again, time to save Internet radio]]>
           </title>
           <publishedAt>2007-03-05T03:36:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-03-05-here-we-go-again-time-to-save-internet-radio</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Just fixed a bit of IE7-only CSS background b0rkeness in this blog theme. Thanks to Michael W. for pointing out the ugliness.</p>

<p>Because this is not my own theme -- and, okay, because it's IE, I'll admit it -- I just stuck a bit of IE7-specific hackery into the stylesheet. Apparently, "*:first-child+html" is still somehow valid CSS.</p>

<p>I would love to do a ground-up stylesheet for this blog without all the hacky legacy stuff. That'll be next on my list of largish projects, probably.</p>]]>
           </body>
           <title>
               <![CDATA[Fixed IE7 CSS ugliness]]>
           </title>
           <publishedAt>2007-03-02T05:10:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-03-02-fixed-ie7-css-ugliness</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>If you spend any time at all reading stuff online, you frequently run into Web pages whose stylesheets don't constrain the width of the text on the page.</p>

<p>At least until we get <a href="http://www.w3.org/TR/2001/WD-css3-multicol-20010118/">CSS3 multi-column support</a> in all the mainstream browsers, doing a multi-column layout is (to quote our esteemed president here in the US) <a href="http://alistapart.com/articles/multicolumnlayouts">really hard work</a>. Most people can't be bothered to do fancy layout stuff, and when you have a big monitor, the end result is ridiculously wide swaths of text that sprawl all the way across the browser window.</p>

<p>People argue about the optimal column width for readability, but <a href="http://www.webusability.com/article_line_length_12_2002.htm">everyone agrees that there is some limit</a> (bonus irony points that the article linked here uses an excessively wide fixed width). </p>

<p>I know about how much my eyes can stand -- eventually I get lost going back to the left-hand side for the next line of text, so I finally sat down and did something I should have done long ago -- made myself a bookmarklet that forces a Web page to a certain width.</p>

<p>It looks like this:</p>

<pre><code>javascript:(function(){
  var d = document;
  var s = d.createElement("style");
  s.setAttribute("type", "text/css");
  var h = d.getElementsByTagName("head")[0];
  h.appendChild(s);
  s.appendChild(d.createTextNode(
  'h1,h2,h3,h4,h5,h6,p,ul,ol,dir,menu,' +
    'div,dt,dd,address,blockquote,pre,br,'+ 
    'hr,dl,table,tbody' +
    '{width:580px!important;text-align:left;}'
  ));
})()
</code></pre></pre>

<p>It just appends an inline style to the page, and forces the width of all block-level elements to 580px -- using an !important rule to override any styles that may be already set directly on elements. </p>

<p>Of course any !important rules set right on page elements could potentially be a buzzkill here, also cases where the page author has done weird stuff like mutating normally inline elements like <code>span</code></pre> to be <code>display: block</code></pre>.</p>

<p>Strip out all the linebreaks and spaces above (also the concat action going with the long string for the CSS rule), drop it in a bookmark, and you're good to go. Your eyes will thank you.</p>]]>
           </body>
           <title>
               <![CDATA[Taming the horrid wide Web]]>
           </title>
           <publishedAt>2007-02-27T04:21:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-02-27-taming-the-horrid-wide-web</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I just recently joined Twitter, and have been enjoying it immensely so far. I like the steady stream of updates, and for someone like me who works at home, it's a nice way to get a sense of what other people I work with are up to during the day.</p>

<p>Being the OCD-type-of-guy that I am, I naturally wanted a simple, consistent way to post my blog updates to Twitter as well. Fortunately the folks at Twitter have <a href="http://twitter.com/help/api">thoughtfully provided a nice API</a> for the service.</p>

<p>Typo doesn't seem to have much in the way of a plugin ecosystem, and I wasn't too thrilled about the idea of hacking Typo source, so I decided to take the easy way out, and do my posts to the Twitter API with a bookmarklet. </p>

<p>I knew there'd be a bit of code involved in scraping the page to get the title and categories for the blog entry in question, so the first thing I needed to do was to embed a script on the page that could pull down a good-sized chunk of JavaScript code. The bookmarklet for that looks like this:</p>

<pre><code>javascript:(
  function () { 
  var scr = document.createElement('script');
  scr.src = 'http://yourdomain.com' +
    '/some_sizable_script.js';
  document.getElementsByTagName(
    'head')[0].appendChild(scr);
} )()
</code></pre></pre>

<p>Just point it at the script you want, strip out all the linebreaks and spaces, and put it in a bookmark. When you click it, it'll pull down the desired file and execute all the code in it in the context of the current page.</p>

<p>Here's the code mine pulls down and runs. (I'm chucking out my Typo-specific stuff in the hope that it'll be more generally useful.)</p>

<pre><code>var timeoutIncr = 0;
var scr = document.createElement('script');
scr.src = 'http://downloads.fleegix.org/fleegix_js' +
    '/releases/fleegix-0.3/fleegix.js';
document.getElementsByTagName(
  'head')[0].appendChild(scr);

var twitterUpdate = function () {
  if (typeof fleegix == 'undefined') {
    timeoutIncr++;
    if (timeoutIncr &gt; 5) { 
      alert('Could not load fleegix.js library.'); 
      return false; 
    }
    setTimeout(twitterUpdate, 3000);
  }
  // -----
  // Do stuff here to grab the blog post title
  // -----
  var s = 'The-blog-post-title';
  if (s.length &gt; 140) {
    s = s.substr(0, 136) + '...';
  }
  s = 'status=' + encodeURIComponent(s);
  fleegix.xhr.doPost(handleTwitterResponse, 
    '/backend_proxy.rbx', s);
};
var handleTwitterResponse = function (s) {
  var resp = eval('(' + s + ')');
  alert('Submitted: ' + resp.text);
}

setTimeout(twitterUpdate, 1000);
</code></pre></pre>

<p>The first thing the script does is go out and grab a copy of the <a href="http://js.fleegix.org/">Fleegix.js JavaScript Toolkit</a>, and add that to the current page, so as to have a working XHR library to do the XHR post. (Typo does actually ship with Prototype, so in theory I could use that, but this way it works no matter the blogging platform) The nice thing about this remote scripting stuff is that the code you want to use can live anywhere on the 'Net you want. Just make sure you're pulling code from a trusted source.</p>

<p>I've added a bit of timeout fu there so that the main code won't execute until it's got a <code>fleegix</code></pre> object to work with. If it never can pull down the fleegix.js file, it will eventually give up with an error.</p>

<p>The <code>twitterUpdate</code></pre> code grabs the title of the blog post and the categories (in my case it uses some ugly DOM-groveling and regex -- you can do it however you like), and formats it as a query-string for an XHR POST.</p>

<p>That takes care of the client side. Since this is an XHR POST, we have the annoying cross-domain security issue to deal with, so we have to submit to a backend page that will proxy the request to Twitter for us.</p>

<p>I initially looked at the <a href="http://rubyforge.org/projects/twitter/">Ruby Twitter gem</a> for a backend script -- reuse is a good thing -- but unfortunately it doesn't seem to be kept up to date with its dependencies. (It wants a very specific version -- not the latest -- of <a href="http://code.whytheluckystiff.net/hpricot/">Hpricot</a> to be installed from WhyTheLuckyStiff's source repo.) </p>

<p>In the end I went with a basic mod_ruby script, since it's just an HTTP proxy -- super-simple, and easily done with the stuff in a base Ruby install. Here's the script:</p>

<pre><code>#!/usr/bin/ruby

require 'base64'
require 'net/http'
require 'cgi'

cgi = CGI.new

email = 'address@yourdomain.com'
pass = 'your-twitter-pass'
auth = Base64.encode64(email + ':' + pass)
status = cgi['status']

h = Net::HTTP.new('twitter.com', 80)
resp, data = h.post('/statuses/update.json',
  "status=" + status,
  { 'Authorization' =&gt; 'Basic ' + auth })

h = Hash.new
h['Content-type'] = resp['content-type']
h['Status'] = resp['status']
h['Content-length'] = resp['content-length']

cgi.out(h) { data }
</code></pre></pre>

<p>As you can see, it's a simple script that posts whatever it gets in the 'status' CGI param to Twitter, and passes the response from Twitter back to JavaScript. Easy as pie.</p>

<p>Sure it's one extra click of a bookmark after finishing a blog post, but I'm really happy I didn't have to muck around in the innards of Typo (making sure it only posts to Twitter on the initial save and not when I update the post, and so on). Plus, this was a nice excuse to play around with bookmarklets. Fun stuff.</p>

<p>Caveat emptor: I've only used this in Firefox 2, although it ought to work in most major browsers -- even IE6.</p>]]>
           </body>
           <title>
               <![CDATA[Fun with the Twitter API -- JavaScript bookmarklets and Ruby]]>
           </title>
           <publishedAt>2007-02-24T04:51:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-02-24-fun-with-the-twitter-api-javascript-bookmarklets-and-ruby</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Ars Technica has some <a href="http://arstechnica.com/news.ars/post/20070222-8908.html">interesting browser market-share numbers</a>.</p>

<p>By most measures, Internet Explorer is losing ground. Depending on whose numbers you're looking at, Safari and Firefox are either holding steady, or gaining.</p>

<p>Just to bring a splash of reality to the WebKit triumphalists in the comments in <a href="http://arstechnica.com/journals/apple.ars/2007/2/22/7187">a related article on Ars</a>, Safari's growth -- even in the rosiest measure -- is 1.7% in absolute figures. The chart shows a 56% percent increase -- but that's relative to its original tiny share.</p>

<p>I actually think it's good having more than just two mainstream browser choices. I'm impressed by what I'm seeing with WebKit, particularly with the speed at which they seem to be fixing all the stupid issues that make developing for Safari 2 so excruciating. It will be interesting to see if Safari can crack 10%. Support for other OSes, while maybe a bit far-fetched at this point, would be a sure-fire way to see that happen.</p>

<p>Lastly, it's also worth noting that the introduction of IE7 hasn't done anything to staunch the steady drip-drip of market share away from Explorer. </p>

<p>Microsoft still has an enormous amount of catching up to do there. IE7 isn't bad, but with all the superior alternatives available, just being Microsoft and being not-terrible just isn't compelling enough. Frankly, I don't think Microsoft can succeed at producing a really killer browser until they resolve all the internal corporate angst about it undermining the monopoly power of their OS.</p>

<p>I'd like to think they can pull it off, but it's so ingrained in their coporate DNA, you have to wonder.</p>]]>
           </body>
           <title>
               <![CDATA[Some browser market-share numbers]]>
           </title>
           <publishedAt>2007-02-24T03:56:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-02-24-some-browser-market-share-numbers</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I was outside today chopping some bamboo in the front yard, when a weird-looking SUV bristling with cameras, antennas, and other electronic crap turned into our cul-de-sac. When it got down to the end and made the circle to go back out, I was able to see the stickers and logos emblazoned all over the sides -- it was one of the trucks from <a href="http://preview.local.live.com/">Mircrosoft Live Local Virtual Earth</a>.</p>

<p>I wish I'd figured out what it was a bit sooner -- I smiled and waved and jumped up and down, but I'm pretty sure it was too late. They seemed like they were in a bit of a hurry. I guess I would be too if I were trying to gets shots of all the roads for the entire city of Houston (the entire country, the entire planet). Busy, busy guys.</p>]]>
           </body>
           <title>
               <![CDATA[Smile for the Windows Live Local camera]]>
           </title>
           <publishedAt>2007-02-19T03:41:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-02-19-smile-for-the-windows-live-local-camera</permalink>
</article>
       <article>           <body>
               <![CDATA[<p><a href="http://www.eduneering.com/">Eduneering</a>, my former employer (the company that bought KnowledgeWire, the Internet startup where I cut my JavaScript teeth) <a href="http://www.eduneering.com/news/29/">has been acquired by Kaplan</a>.</p>

<p><a href="http://www.kaplan.com/">Kaplan</a> is a big educational company, known for prep courses for admissions tests like the SAT, GRE, and so on. Sounds like a good fit for Eduneering -- and Kaplan will find they have acquired some amazing talent along with all the other assets Eduneering has.</p>]]>
           </body>
           <title>
               <![CDATA[Eduneering acquired by Kaplan]]>
           </title>
           <publishedAt>2007-02-17T17:18:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-02-17-eduneering-acquired-by-kaplan</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Okay, so it's not really such a mystery, it just sounded good as the title. </p>

<p>I'm catching up on posting some of the stuff we trip on while working on Cosmo, and this time around it's a Firefox bug -- when working with absolute-positioned, z-indexed divs that contain text inputs, sometimes the flashing cursor/caret in the text box mysteriously disappears. The box has focus, and you can type -- text appears, but you have no feedback as to where you're typing.</p>

<p>I can remember seeing this problem starting some years back, in the original Mozilla browser. </p>

<p>At the time I had started doing all my development work in Mozilla, but all our users were naturally using IE (except those cold-dead-fingers dudes at the time still clinging to Netscape 4.08, and the art-department freaks trying to log in with the new Safari browser). We had some pop-up interface widgets that used a multi-tab strategy to break the form up, and some of the time I'd lose the caret in text inputs in some chunks of the form.</p>

<p>Since I was the only one using Moz (in fact, I can recall my supervisor at one point huffily demanding I pull up a 'real browser' for some bit of testing), it was just an annoyance to me and that was it.</p>

<p>Well as you can see by the <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=167801">Mozilla Bugzilla report for this bug</a>, this screwy behavior was first reported in September of 2002, and it's still not fixed in any Mozilla release. Probably back then it wasn't such a big deal, but as time has passed, the annoyance factor on it has increased substantially. You can almost feel the angst in the post by one commenter, from back in November of 2005:</p>

<blockquote>
    <p>This is an incredibly painful bug and not only makes applications look bad, but also makes FireFox look bad. It will become more and more visible as AJAX applications start proliferating. Please please please fix this bug</p>
</blockquote>

<p>The good news is that it's actually fixed. The bad news is that it's fixed in Firefox trunk, which means no one actually gets the aforementioned fix until fall or winter of this year. </p>

<p>Of course now I know what actually causes it -- a scrollable div behind the one with the text inputs (check the <a href="https://bugzilla.mozilla.org/attachment.cgi?id=99019">test case</a>, you can see the caret emerge as you type past the edge of the underlying div) -- and it looks like there are some reasonable workarounds, so we won't have to play "guess where you're typing" in the next Cosmo release.</p>]]>
           </body>
           <title>
               <![CDATA[Mystery of the disappearing cursor/caret]]>
           </title>
           <publishedAt>2007-02-14T06:30:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-02-14-mystery-of-the-disappearing-cursor-caret</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>This is a bug in Safari that some of our Cosmo tests turned up. </p>

<p>I had to do bit of digging around to figure out what was going on, so I thought I'd post it here and maybe save other people some trouble if they run into the same thing.</p>

<p>When instantiating a JavaScript Date with a month parameter higher than 11 or less than 0 (December and January, in the zero-based world of JavaScript Dates), the date should 'wrap around' to the correct month in the following/previous year (see ECMAScript 262 Third Edition, section 15.9.1.12, MakeDay).</p>

<p>Safari can't handle these out-of-range parameters properly, but doesn't even have the good sense to fail in those cases -- it just produces some seemingly random date. The <code>setMonth</code></pre> method of Date unsurprisingly has the same issue. This problem is documented in <a href="http://bugs.webkit.org/show_bug.cgi?id=4892">WebKit bug 4892</a>.</p>

<p>Unfortunately this is one of those "doctor it hurts when I do this" kind of problems -- the only practical solution is just not to expect intelligent wraparound from Dates in Safari.</p>

<p>Happily, the problem is fixed in the WebKit nightlies, so when Apple revs Safari, this should be fixed. Fortunately Safari users are a relatively small group, and very likely to upgrade, so hopefully this won't be a thorn in our side that much longer.</p>]]>
           </body>
           <title>
               <![CDATA[JavaScript Date constructor wraparound broken in Safari 2]]>
           </title>
           <publishedAt>2007-02-13T03:21:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-02-13-javascript-date-constructor-wraparound-broken-in-safari-2</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>It seems that Steve Yegge has received word from the mysterious cabal of shadow-government dudes who control mainstream programming languages, and <a href="http://steve-yegge.blogspot.com/2007/02/next-big-language.html">he knows what they've chosen as the next big language</a>. </p>

<p>Apparently, it's JavaScript.</p>

<p>He writes:</p>

<blockquote>
    <p>And I got a tip — a rather detail-packed one at that — as to which way the wind is blowing. Let's face it: I've been digging into this story for years, so it should be no surprise that I got the scoop.</p>
</blockquote>

<p>He prudently refuses to reveal its name -- if he were to say too much, he'd probably vanish, only to show up some weeks later, wandering around in a forest with some kind of extra-terrestrial computer chip in the back of his neck.</p>

<p>Read the entire description, but he's clearly talking about JavaScript 2. </p>

<p>Rule number one -- "C-like syntax," rules out Ruby (and Python too, if you're in that camp). All those semi-colons and curly braces are pretty noisy, but, as Steve points out, "Bad or not, NBL will have approximately C-like syntax because if it doesn't, most programmers won't give it a second glance." Interestingly, I happen to know at least one otherwise very sharp programmer who has turned up his nose at Ruby specifically because it doesn't look like C. Yes, it really happens.</p>

<p>The other obvious bits:</p>

<blockquote>
    <p>As a special sneak preview, its static type system will include a "standard" class system (i.e. the kind you're used to if you do any conventional OOP using C++ or Java or Python or whatever, as opposed to Common Lisp's object system or some other unconventional one.) Not that the standard system is any better, but it's what people want.</p>
</blockquote>

<p>People always seem to bend over backward to try to emulate normal class-based inheritance with JavaScript, so I suppose it makes sense to give people what they think they want.</p>

<p>Nothing terribly surprising here, but the cloak-and-dagger routine is entertaining -- and Steve's points about what it takes to make a successful mainstream language are interesting and enlightening. Also, the guys in the comments shouting out stuff like "Dylan?" and "Fortress!" are just hysterically funny, whether they mean to be or not.</p>]]>
           </body>
           <title>
               <![CDATA[Steve Yegge: JavaScript is the Chosen One]]>
           </title>
           <publishedAt>2007-02-12T04:17:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-02-12-steve-yegge-javascript-is-the-chosen-one</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I got my wife a Roomba for Christmas. She's really hard to shop for, but she seemed pleased and kind of surprised to get it. </p>

<p>I asked her what she was going to name him, and she decided on 'Ba-kun.' It's kind of a play on words with the Japanese katakana pronunciation of both 'vaccuum' (bakyuumu) and 'bug' (baggu). 'Kun' is the name suffix you use with young men or boys, so I guess he's a boy.</p>

<p>We finally got him out of the box and put him to work the other day, and as you can imagine, the kids totally went nuts. </p>

<p>They just can't stay away from him, and of course the sudden course changes he makes as he drives around means he keeps banging into them and changing course again. They don't mind; they just laugh like loons. But of course it messes up the vacuuming pattern, which is kind of the entire point of a Roomba.</p>

<p>Felt kind of odd hollering at them, "Boys, leave your mom's robot alone, and let him do his job."</p>

<p>It does take awhile, but it actually does a pretty good job, even with all the toy clutter we have. I'm looking forward to seeing how it does on the carpet upstairs.</p>]]>
           </body>
           <title>
               <![CDATA[Welcoming Ba-kun, our new Roomba]]>
           </title>
           <publishedAt>2007-01-26T05:50:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-01-26-welcoming-ba-kun-our-new-roomba</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>PPK over at QuirksBlog has a nice entry on the <a href="http://www.quirksmode.org/blog/archives/2007/01/again_javascrip.html">latest round of discussions about JavaScript libraries</a> in the JS/DOM/CSS blogging world.</p>

<p>The JS library thing continues to provide rich fodder for discussion because it involves so many different layers -- what type of app you want to use the library for, your level of skill with native JS/DOM/CSS, the coding style you're comfortable with, your tolerance for sloppy/undocumented code, your tolerance for download size, your tolerance for corporate overlords, how well your goals align with the goals of the toolkit developers, and so on.</p>

<p>PPK starts off by referencing <a href="http://www.kryogenix.org/days/2006/12/24/the-fog-of-libraries">a post I read last week or so from Stuart Langridge</a> (author of DHTML Utopia, and the tech reviewer for my book), where Stuart seems to moderate a lot of the serious anti-library leanings he used to have. Ultimately however, I don't really buy PPK's final point -- he believes that the current lack of doco means that the only people who can use the toolkits are the experts who don't need them. He writes:</p>

<blockquote>
    <p>Right now it doesn't seem that Stuart's nine-to-fivers will actually benefit from libraries, unless they're pretty decent scripters to begin with, which makes their using a library less necessary (hence less likely).</p>
</blockquote>

<p>First of all, I think there are plenty of nine-to-fiver developers out there plugging in one toolkit or the other, squinting at the scant online docs, and hammering at it until they get it to do what they want. For most of those guys it still beats trying to write a CSS fadeout transition from scratch. And second, it's pretty obvious even to a diehard do-it-yourself-er like me that even experts can get a lot of benefit from leveraging the work of a larger group of experts like themselves.</p>

<p>Similarly to Stuart, my opinion of the use of libraries or toolkits has evolved, as the kinds of things I want to do with JavaScript has changed, and as the quality of the available libraries has improved. Relying on a set of tools used by a larger group of developers gives you significantly more power with a lot less effort than if you were to try to do all that stuff yourself.</p>

<p>But you do give up some degree of freedom. In the words of <a href="http://www.imdb.com/Title?0106677">Wooderson</a>, "Oh, yes you do."</p>

<p>First of all, you have to do some stuff the toolkit's way whether you like it or not. I've used both Dojo and Prototype now enough to know that both of them do things in ways that seem less than optimal to me. Dojo's packaging and namespacing stuff feels kind of Byzantine and overengineered to me, for example. Prototype's <code>Event.observe</code></pre> is pretty underwhelming, and I find the <code>bindAsEventListener</code></pre> thing seriously awkward. Not to dump on those two libraries -- in return I get a bunch of well-tested functionality for free.</p>

<p>More importantly, you become dependent on the developers of the library to implement the features and fixes you need. If you've got that library code rooted deep in your app, it becomes a genuine concern to you that the library developers <em>not do things that will totally break your shit.</em> In theory, you do always have the freedom of not upgrading your main JavaScript library. Ever. But how appealing is that in a serious Ajax app that's under heavy development?</p>

<p>We use Dojo in the Cosmo app, and the news that <a href="http://dojotoolkit.org/pipermail/dojo-contributors/2007-January/005939.html">Dojo is jumping from 0.4 to 0.9, with no backward-compatibility code in the new version</a>, doesn't give me a warm, fuzzy feeling inside. Libraries are supposed to make your life easier, and the words "comprehensive porting guide" sound suspiciously like "a bunch of extra work" to my jaded ears. I'll withhold judgement until I see how extensive the changes are.</p>

<p>I feel like now I have a pretty even-handed view of the positives versus the perils of using a third-party toolkit in your Web app. The peril part is one of the reasons I keep working on the <a href="http://www.fleegix.org/pages/downloads/">Fleegix.js library</a> for use in my personal projects. Okay, that, and the fact that I just genuinely enjoy playing with this stuff.</p>]]>
           </body>
           <title>
               <![CDATA[Ongoing JavaScript library discussion]]>
           </title>
           <publishedAt>2007-01-21T04:29:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-01-21-ongoing-javascript-library-discussion</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Linden Lab has <a href="http://lindenlab.com/press/releases/01_08_07">released the source code for the Second Life client application</a> under the terms of the <a href="http://secondlife.com/developers/opensource/gplv2">GNU General Public License, version 2.0</a>.</p>

<p>This is great news for Second Life, and really opens up an amazing new set of possibilities for what SL could develop into -- as well as a lot of interesting questions about things like property rights in the digital realm.</p>]]>
           </body>
           <title>
               <![CDATA[Linden Lab open-sources  Second Life client]]>
           </title>
           <publishedAt>2007-01-09T06:39:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-01-09-linden-lab-open-sources-second-life-client</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I just saw this in a blog post yet again -- and from someone who is otherwise quite a good writer. I guess now is as good a time as any to bring back the English Fascist.</p>

<p>It's not "peak [someone's] interest." The correct word is 'pique.' </p>

<p>'Peak' is an intransitive (can't take an object) verb that means "reach the highest possible level," e.g., "The shrillness of Geddy Lee's shrieking peaks in the 'Temples of Syrinx' section of <em>2112.</em>"</p>

<p>I guess the connection there is that a 'peak' is high, so you use that word to indicate that someone's interest (or whatever) has been 'heightened.' It's completely wrong, but I guess I can see how someone would wind up there.</p>

<p>Sadly though, I've also seen the same misuse with 'peek,' another intransitive verb which of course means "to take a little look." That one is not just wrong, it's bizarre. ("it peeked my interest"?).</p>

<p>The word you want here is 'pique' -- a transitive verb that means "to excite, arouse, provoke [something]." Hence, "pique my curiosity" means "arouse my curiosity." (As a noun it means "resentment or irritation" -- a separate definition.)</p>]]>
           </body>
           <title>
               <![CDATA[Pique, peak, peek]]>
           </title>
           <publishedAt>2007-01-05T06:14:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-01-05-pique-peak-peek</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Happy new year, everybody.</p>

<p>According to my Webalizer stats, EpiphanyRadio had just over 10,000 visitors in the 24-hour period of 12am to 12pm of December 30th. The final hit count was about 280,000 -- kept pretty low by changing over to that static page. Usage fell off really quickly by the next day -- about 1200 visitors, and just over 53,000 hits for 12/31. </p>

<p>The servers filled up right away -- there's just 80 connections, so very few people were able to listen, obviously. I'm hoping at least a few of the people will come back again to check out the music -- there's some really amazing stuff in there.</p>]]>
           </body>
           <title>
               <![CDATA[Happy new year, final EpiphanyRadio Digg report]]>
           </title>
           <publishedAt>2007-01-03T06:43:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2007-01-03-happy-new-year-final-epiphanyradio-digg-report</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Ouch, mommy. Around noon today, I noticed my Web server becoming increasingly sluggish. Telnet to 110 and 25 were working fine, but Apache was non-responsive, and SSH was giving me the ol' silent treatment as well. After a seriously lengthy remote reboot process, I logged in and had a look at <code>top</code></pre>, and there was a mass of <code>apache</code></pre> processes glued to the top of the readout.</p>

<p>In the last couple of days I've been getting a bunch more music submissions and comments from the station than usual, so I had a quick look at the logs for the EpiphanyRadio site -- and noticed that today's file was frigging <em>enormous.</em> I hadn't been running Webalizer stats on the site since the most recent rewrite, so I ran the last couple of months of logs, and daily usage was the normal 100 visitors, 3000 hits or so per day -- all the way up to today. Today's stats around noon were 4000 visitors, 200,000 hits or so (Note: The figure of 7000 I had here earlier for visitors was actually the 'pages' column in the report).</p>

<p>I was figuring a nice DDOS like we had on the mail server awhile back, so I just threw up a static page in place of the Ajaxey single-page Web-app that's normally there. The site is a full-on Dojo app that does this continuous polling to keep the number of listeners and currently playing track updated on the page, and rotates the banners and album cover images.</p>

<p>I was on my way out the door to my nephew's birthday party, but I did have a quick look at the mirror servers for the stream, and oddly, they were all showing full-to-capacity usage. All 80 128Kbps connections were full -- a hell of a lot of actual people actually listening to the stream.</p>

<p>So, after supper tonight, I added a custom log directive to the server config to start grabbing the referers and sticking them in a separate file. Tailing that dude, now I can see that all this lovely traffic is from <a href="http://digg.com/tech_news/100_RIAA_free_radio">EpiphanyRadio showing up on Digg</a> (1117 diggs as of now). Wa-hoo!</p>

<p>Guess I got off pretty easy -- with the static page, even the rinky dink box it's running on is basically idling. I'll post a final note on what the stats looks like when the wave totally passes.</p>

<p>Update: Must be the much-vaunted Digg Effect -- it looks like EpiphanyRadio is also sitting in the top ten on <a href="http://del.icio.us/popular/">del.icio.us/popular</a>.</p>]]>
           </body>
           <title>
               <![CDATA[EpihanyRadio gets Dugg]]>
           </title>
           <publishedAt>2006-12-31T03:16:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-12-31-epihanyradio-gets-dugg</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Let the hating begin. </p>

<p>Dave Winer finally has an actual look at the JSON format, and <a href="http://scripting.wordpress.com/2006/12/20/scripting-news-for-12202006/">to his horror, finds that "IT’S NOT EVEN XML!"</a> Ah, the hideous, "blood, guts, veins in my teeth" humanity of it all. In summary, here are his impressions:</p>

<blockquote>
    <p>No doubt I can write a routine to parse this, but look at how deep they went to re-invent, XML itself wasn’t good enough for them, for some reason (I’d love to hear the reason). Who did this travesty? Let’s find a tree and string them up. Now.</p>
</blockquote>

<p>A lot of folks in the comments for this deeply silly post of Dave's take great pains to try to smooth his ruffled feathers by assuring him that the use of JSON, thank heavens, is pretty much limited to the world of Ajax/JavaScript programming. Fortunately for right-thinking people everywhere, Simon Willison has taken the time to write a nice, measured post in reponse on his blog that <a href="http://simonwillison.net/2006/Dec/20/json/">explains why this is simply not so</a>.</p>

<p>I've done a fair amount of work with XML and JSON -- both in client-side JavaScript, and in server-side languages such as Ruby, PHP, and C#. And I can say pretty definitively that JSON is a reinvention of XML in much the same way that my Volkswagen GTI is a reinvention of the Ford Explorer.</p>

<p>Seriously, If you just want to serialize some data (and of course, if you're not one of the inventors of XML-RPC), there are lots of <a href="http://www.json.org/xml.html">good reasons you might prefer JSON to XML</a>.</p>]]>
           </body>
           <title>
               <![CDATA[Dave Winer, JSON hater]]>
           </title>
           <publishedAt>2006-12-22T03:43:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-12-22-dave-winer-json-hater</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Looks like Google is voting no on SOAP -- as an <a href="http://radar.oreilly.com/archives/2006/12/google_depreciates_SOAP_API.html">entry on the O'Reilly Radar blog shows</a>, they've deprecated their SOAP search API, and are directing people to their <a href="http://code.google.com/apis/ajaxsearch/">AJAX Search API</a> instead.</p>

<p>I'm not a huge fan of SOAP. It's pretty telling that somehow the letters don't stand for anything anymore -- it's just SOAP. "Okay, right ... so, it's not 'simple,' anymore, but we don't know what the hell it is now." That's worse than those silly recursive acronyms, and easily as irritating as words like "Ajax" that look like acronyms, but aren't -- "it's just a <em>shorthand</em>." Riiiight.</p>

<p>My experience with SOAP is that it's overly convoluted, and the tools are finicky to set up and use. When something goes wrong, it's hard to figure out the cause without firing up Ethereal. I'm actually happy to see Google moving away from SOAP -- I think it's a win for simplicity over needless complexity.</p>

<p>However, having said that, this change at Google does impact me a little because there is code in my book that uses the Google SOAP API.</p>

<p>The Ajax search app in Chapter 7 hooks into the Google SOAP API (among others) using a PHP backend proxy page (there's code for both the compiled-in extension and the PEAR library), and now obviously anyone wanting to try that code out will be SOL, because Google is no longer issuing keys to use that API.</p>

<p>It looks like they continue to support existing users for awhile at least, which is nice. So if any of y'all are reading Chapter 7, and for whatever reason <em>really, really</em> want to play around with Google's SOAP API, send me an e-mail, and I can dig up the key I got when I was working on that part of the book.</p>]]>
           </body>
           <title>
               <![CDATA[Google votes no on SOAP]]>
           </title>
           <publishedAt>2006-12-20T22:53:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-12-20-google-votes-no-on-soap</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Continuing on with the self-promotion theme I started in the last post -- a few weeks ago <a href="http://www.mikeriley.com/">Mike Riley</a> interviewed me for Doctor Dobb's Journal about my book and about working at OSAF.</p>

<p>It looks like the podcast, which he has titled <a href="http://www.ddj.com/dept/webservices/196603667?cid=RSSfeed_DDJ_All">AJAX, Cosmo, and Hemispheres</a>, has made it up on the site for download. I'm seriously amazed at how far good audio editing can go to make you sound like you're not a complete, blithering idiot.</p>]]>
           </body>
           <title>
               <![CDATA[Interview podcast on Dr. Dobb's ]]>
           </title>
           <publishedAt>2006-12-16T03:26:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-12-16-interview-podcast-on-dr-dobbs</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Interesting to see the <a href="http://ajax.phpmagazine.net/2006/11/top_10_ajax_books_2006_quarter.html">top 10 list of Ajax books</a> sold from the Ajax Magazine site. Apparently, my book is at number four. </p>

<p>Not too bad I guess -- except that those big ol' foam rubber hands probably don't look as cool with all four fingers pointing up.</p>]]>
           </body>
           <title>
               <![CDATA[I'm number four!]]>
           </title>
           <publishedAt>2006-12-14T03:46:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-12-14-im-number-four</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I've just upgraded to Ubuntu Edgy, and it's kind of eerie now having Web video that works in most places.</p>

<p>Some very nice video tutuorials over at the <a href="http://developer.yahoo.com/yui/theater/">YUI Theater</a>. I'm particularly enjoying Professor Crockford's talk on <a href="http://yuiblog.com/blog/2006/11/27/video-crockford-advjs/">Advanced JavaScript</a>. Always nice to see yet another way to create a singleton for namespacing in JS:</p>

<pre><code>var foo = function () {
    return {
        bar: 'bar',
        baz: function () {
            this.bar = 'foo';
        }
    };
}();
</code></pre></pre>

<p>My favorite quote so far: "... and pseudoclassical inheritance is for elderly programmers."</p>]]>
           </body>
           <title>
               <![CDATA[YUI Theater]]>
           </title>
           <publishedAt>2006-12-07T06:02:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-12-07-yui-theater</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Now this makes a bit more sense to me -- Dan Webb's <a href="http://www.danwebb.net/2006/11/17/rjs-minus-r/">MinusR/MinusMOR</a> (some other <a href="http://www.lukeredpath.co.uk/2006/11/17/rjs-templates-without-the-r">good commentary on Luke Redpath's blog</a>). Rather than coding in server-side Ruby and trying to convert that to client-side JavaScript, how about coding in JavaScript that allows embedded Ruby code in it?</p>

<p>His comment about using server-side code in one language to produce client-side code in another is spot-on:</p>

<blockquote>
    <p>When RJS first came out I was quite impressed with the Ruby to JavaScript translation stuff but it’s limitations (and that of lots of other similar attempts at 'compiling down to JavaScript' like Google Web Toolkit) shine through after the lightest of uses.</p>
</blockquote>

<p>With RJS (and other similar approaches), if you want to do something complicated, it's easy to end up with a Frankenstein-monster approach with lots of heredocs or concatenated strings of raw JavaScript.</p>

<p>This reverse-RJS turns that notion neatly on it's head. Your target is code that runs in the client-side environment -- why not start in there -- in JavaScript -- and allow islands of the server side language wherever you need it?</p>

<p>Then you end up with pretty reasonable looking code like this:</p>

<pre><code>if (someClientSideVariable) {
    $('a').update(&lt;%= js render(:partial =&gt; 'thing') %&gt;);
} else {
    $('b').update(&lt;%= js render(:partial =&gt; 'thong') %&gt;);
}
</code></pre></pre>

<p>I'm sure it depends on how complex your client-side code is, and how comfortable you are with JavaScript -- but this seems like a nice compromise that would you all the flexibility you'd get from writing pure client-side code, but a lot of extra power to tap the tasty Rails goodness going on server-side.</p>]]>
           </body>
           <title>
               <![CDATA[RJS in reverse -- JRS?]]>
           </title>
           <publishedAt>2006-11-25T05:44:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-11-25-rjs-in-reverse-jrs</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Excellent article over at Dev.Opera on <a href="http://dev.opera.com/">Efficient JavaScript</a>. It contains a load of different tips and techniques for improving the performance of your Ajax Web application -- looking at JavaScript, interacting with the DOM, and document loading.</p>

<p>Seems like now that the Ajax revolution has taken hold everywhere, more and more people are working proactively to manage client-side bloat. Agility and responsiveness are supposed to be one of the key advantages of an Ajax Web app over both traditional installed apps and old-fashioned Web apps, so performance is a good thing to start thinking about before it becomes a problem.</p>]]>
           </body>
           <title>
               <![CDATA[Opera article on efficient JavaScript]]>
           </title>
           <publishedAt>2006-11-17T04:22:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-11-17-opera-article-on-efficient-javascript</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Man, the virtual world of Second Life seems to be awash in even more drama than usual. That kind of virtual milieu always provides all kinds of opportunities for social drama between players, but this time it's the entire world, and its creators, <a href="http://lindenlab.com/">Linden Lab</a>.</p>

<p>I haven't spent any time in SL in months, but I still have friends and acquaintences who spend lots of time on the Grid. In the past couple of weeks, I've gotten a real earful about the hefty increases in costs for purchase and maintenenace of private islands (on the order of 50%), and the horrors of the evil CopyBot. CNET News.com has <a href="http://news.com.com/Second+Life+faces+threat+to+its+virtual+economy/2100-1043_3-6135699.html?tag=nefd.lede">a good article about the ongoing flap</a>.</p>

<p>If I were an SL content creator, I'd be freaking out about CopyBot too -- it basically allows you to make a perfect copy of any object, irrespective of the permissions you might or might not have on it.</p>

<p>It's a the same problem first seen with <a href="http://en.wikipedia.org/wiki/Sony_Corp._v._Universal_City_Studios">Sony Corp. of America v. Universal City Studios, Inc.</a> (a.k.a. the "Betamax Case") in the US Supreme Court, it's hard to declare copying technology illegal unilaterally if it has legitamate uses.</p>

<p>In the CNET article, Baba Yamamoto, a member of the group that created CopyBot, explains that its original purpose wasn't illegal copying of objects:</p>

<blockquote>
    <p>Yamamoto told CNET News.com that CopyBot was created as a tool for testing and demonstrations and was never intended to be used for illegal theft. But because the tool was created using an open-source license, some Second Life users have gotten hold of it and are now freely using and distributing it.</p>
</blockquote>

<p>Just like other copying and distribution tools like filesharing networks like BitTorrent, it's easy to see the legit purposes people might have for them, but it's just as easy to use them to violate copyright.</p>

<p>It's an issue that has plagued content creators since the creation of the player piano, and the tools for making copies just keep getting easier to use, and the fidelity of the copies just gets better and better. </p>

<p>In the digital world, copies are perfect, and trivial to make -- so copy protection (euphemistically called 'digital rights management') has to strike a balance between protecting the content from copying, and allowing easy access for legitamate use. Any copy protection can be broken -- as computer-security guru Bruce Schneider famously said, "trying to make digital files uncopyable is like trying to make water not wet."</p>

<p>Fortunately the Lindens can react a little bit faster to these kinds of developments than can society at large (hey, they literally run the SL world), so in this case, it looks like after a brief period of head-scratching, they have decided pull out the Terms of Service stick, and call CopyBot use to make unauthorized copies a TOS violation which will get you banned.</p>

<p>Interesting though that they are not banning CopyBot outright, or rolling out an update to the SL client that would break it. I think that's the right decision, since CopyBot clearly has legitimate uses -- despite all the screaming to the contrary from the content creators. Besides, DRM will always be cracked, and the Lindens shouldn't be squandering their resources on a silly ongoing DRM arms-race which they'll never win.</p>]]>
           </body>
           <title>
               <![CDATA[Second Life drama -- tier increases and CopyBot]]>
           </title>
           <publishedAt>2006-11-16T06:11:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-11-16-second-life-drama-tier-increases-and-copybot</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>JavaScript, as a client-side language, has somewhere between slim and nothing when it comes to timezone support -- it's pretty much limited to getting the offset from GMT for whatever timezone the local machine happens to be set to.</p>

<p>Thinking about ways to fill in this gap, I've been spending some time the past couple of weekends working on a real timezone solution for working with dates in JavaScript.</p>

<p>I started with some code to parse the <a href="http://www.twinsun.com/tz/tz-link.htm">Olson timezone database</a> (AKA the tz database, the zoneinfo database), and then used that to start implementing a complete drop-in replacement for JavaScript Date with full timezone support.</p>

<p>What I ended up with was something I'm calling XDate/XDateTime (because it's 'extended' functionality beyond the native JS Date -- well, and also because the letter 'X' is just cool). It's API-compatible with the JavaScript Date (all the same setters and getters, the constructor works pretty much the same way), but has full Olson-based timezone support.</p>

<p>I've got an <a href="http://www.fleegix.org/demo/xdate.html">XDate demo page</a> set up with some documentation, and also the actual code and the North American timezones ('America/Los_Angeles,' 'America/Chicago,' etc.) loaded up for anyone who's interested in having a look at it. It's also got links to the source code for the XDate/XDateTime objects, as well as the Olson timezone parsing code.</p>]]>
           </body>
           <title>
               <![CDATA[XDate: JavaScript dates with real timezone support]]>
           </title>
           <publishedAt>2006-11-04T02:13:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-11-04-xdate-javascript-dates-with-real-timezone-support</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I'm excited to announce that Cosmo 0.5 is out the door, including all the Web UI code merged in from the Scooby project. </p>

<p>The other biggie from the UI perspective is all the work we did on recurring events. This is some of the most interesting and challenging Web UI work I've ever had the pleasure to work on -- and given the complexity, kept surprisingly clean by some judicious use of of the publish-and-subscribe model provided by <code>dojo.event.topic</code></pre>. Man, that is some seriously tasty Kool Aid.</p>

<p>Also in this release is the move to a Hibernate/relational-DB storage layer that will offer much better performance, and allow Cosmo to scale.</p>

<p>Cosmo comes with a bundled Tomcat server, so it's falling-off-a-log easy to install and play around with. Release notes, and info on how to download and install Cosmo can be found at <a href="http://cosmo.osafoundation.org">the Cosmo project Web site</a>.</p>

<p>If you need some help getting Cosmo running, or just want to let us know what you're doing with it, give us a shout in the #cosmo IRC channel on Freenode.</p>]]>
           </body>
           <title>
               <![CDATA[Cosmo 0.5 released]]>
           </title>
           <publishedAt>2006-11-03T06:23:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-11-03-cosmo-0-5-released</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>When is an Array not an Array? When it's off in another window, apparently. </p>

<p>I've just found that when you reference a JavaScript Array object in another window (in this case, in an iframe), the normal <code>(myArray instanceof Array)</code></pre> test fails. Googling led me to some <a href="http://www.thescripts.com/forum/thread91190.html">commentary from Professor Crockford</a> on the whys and wherefores of this weird behavior:</p>

<blockquote>
    <p>When you say 'Array', you are talking about 'window.Array'. 'window' is the browser's context object, and you get one per page (or frame). All of the arrays created within a context will have their constructor property set to 'window.Array'.</p>
    
    <p>An array created in a different context has a different window.Array, so your test</p>
    
    <p><code>myArray instanceof Array</code></pre></p>
    
    <p>fails. The ECMAScript standard does not discuss multiple contexts, even though virtually all implementations support them. The ECMAScript standard also fails to provide a reliable technique for testing the type of arrays.</p>
</blockquote>

<p>Yeah, the <code>typeof</code></pre> value for an Array is just the bland ol' 'Object.' Looks like if you don't care about Safari you can test for the presence of the word 'Array' in <code>.constructor.toString()</code></pre> of the object in question. Firefox and IE will acknowledge that, yes, this  thing is an Array -- but Safari designates the constructor method simply as "(Internal Function)." Nice, minimalist design -- much like a one-button mouse. And about as useful.</p>

<p>Crockford's suggestion for winnowing out Arrays from other types of Objects is to check for a well-known Array method like <code>sort</code></pre> in the object. That seems pretty hacky, and in my case all I was trying to do was JSONize the Array -- so it was simple enough to do the serialization in the window with the Array, and reference that string value from the other.</p>]]>
           </body>
           <title>
               <![CDATA[Arrays and instanceof with iframe]]>
           </title>
           <publishedAt>2006-10-27T04:32:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-10-27-arrays-and-instanceof-with-iframe</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Looks like <a href="http://download.dojotoolkit.org/release-0.4.0/">Dojo 0.4.0</a> has officially dropped. I'm really happy to note that this release contains a lot of the date manipulation code I originally wrote for OSAF to be part of Cosmo -- so what was originally <code>Date.add</code></pre> and <code>Date.diff</code></pre> in our custom library is now <code>dojo.date.add</code></pre> and <code>dojo.date.diff</code></pre>. Pretty exciting stuff.</p>]]>
           </body>
           <title>
               <![CDATA[Dojo 0.4.0 released]]>
           </title>
           <publishedAt>2006-10-24T19:40:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-10-24-dojo-0-4-0-released</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I would have thought they'd have fixed this bug in Firefox by now, but I just ran into it again. I can remember bumping my head on this about a year and a half ago.</p>

<p>I have a pop-up window that invokes an XHR request to re-render its opener window (the window that spawns the pop-up), with a call like <code>opener.doUpdateWithXHR()</code></pre> or  whatever. It's supposed to pull down some content from the server and repaint the main window.</p>

<p>This works fine with the initial call, but if you close the pop-up window, all subsequent attempts to make requests with the same XHR object result in this little gem of an error: <code>"Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIXMLHttpRequest.open]"</code></pre> Has a sort of sparse elegance to it, I think.</p>

<p><a href="http://the-stickman.com/web-development/javascript/iframes-xmlhttprequest-bug-in-firefox/">This guy reports the same problem</a>, but with calling XHR in the parent of an iframe that he removes. He points to a <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=249843">Mozilla bug for the issue</a>, opened in ... July of 2004.</p>

<p>The workaround, of course, is to call your function in the opener/parent window through setTimeout, to force it to execute in the context of that window. Make a function in your main window like this:</p>

<pre><code>function doUpdateWithXHRFromPopup() {
    setTimeout(doUpdateWithXHR, 0);
}
</code></pre></pre>

<p>And call that function from your popup/iframe instead of referencing <code>doUpdateFromXHR</code></pre> directly. (Another less-optimal workaround would be just to create a brand-new XHR object for the request.)</p>

<p>I wonder if or when they ever plan on fixing this. They still have it flagged as 'New' in Bugzilla. I know it's an Ajaxey, Web 2.0 world and all, but it's not like pop-ups/iframes and XHR are some sort of matter and anti-matter combination. You ought to be able to use the old stuff and the new stuff together without them going kerblooey.</p>]]>
           </body>
           <title>
               <![CDATA[XMLHttpRequest and 0x80004005 (NS_ERROR_FAILURE) error]]>
           </title>
           <publishedAt>2006-10-21T07:13:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-10-21-xmlhttprequest-and-0x80004005-ns_error_failure-error</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>What was an easy upgrade on my home machine running Ubuntu Breezy turned into a horrid, cruel, excruciating process on this Debian server. </p>

<p>I was blown away by how smoothly the Rails migration went for the database (although Postgres 8.1 was little persnickety about some copy-pasted non-ASCII characters in a couple of posts in from the old 7.4 DB).</p>

<p>However, the weird flakiness of Typo once I got it up onto the production machine here was totally perplexing. Different errors in the log every time -- but always with the same consistent, fatal 500-error kerblooey.</p>

<p>As it turns out the problem was the <code>mod_fcgid</code></pre> FastCGI module for Apache. Strangely, the same version of it runs Typo like a champ on them home machine. Not so much up on the server.</p>

<p>After wasting a couple of hours staring at the Rails logs, and multiple instances of  that charming "Controller stack got out of kilter!" error message, I finally got the bright idea to swap out <code>mod_fcgid</code></pre> for the older <code>mod_fastcgi</code></pre>. Bingo, Typo is as happy as can be. I want those two hours of my life back.</p>

<p>I guess I wouldn't have had this problem in the first place if I were using Mongrel like all the cool kids.</p>

<p>In any case I am now running Typo 4, which gives me access to some shiny new features, like spam controls for comments, and this sexy new theme -- my take on the <a href="http://proofread.digital-achievement.com/catalog/themes/view/33">IAmRice</a> theme by <a href="http://iamrice.org/">Damien Tanner</a>.</p>]]>
           </body>
           <title>
               <![CDATA[Typo upgrade]]>
           </title>
           <publishedAt>2006-10-04T05:51:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-10-04-typo-upgrade</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>A reader's comment on a previous post has prodded me to update the JavaScript form-data serializer in the <a href="/pages/downloads/">download section</a> to use the newer <code>encodeURI</code></pre> so it can handle non-ASCII characters. Bye-bye, IE5 support.</p>]]>
           </body>
           <title>
               <![CDATA[Update for JavaScript form serializer]]>
           </title>
           <publishedAt>2006-09-26T23:04:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-09-26-update-for-javascript-form-serializer</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I spent part of this afternoon showing my oldest boy (he's four) how to use my old <a href="http://search.ebay.com/search/search.dll?from=R40&satitle=mighty+men+monster+maker">Mighty Men & Monster Maker</a> set. I just got the thing back from my older brother, who had taken it from my mom's place years ago to play with it with his kids (okay, maybe just to play with it). He did a really good job of keeping all the pieces together and keeping it in good shape.</p>

<p>You choose a combination of head, torso, and leg plates, and stack them in this little tray together. Then put a piece of paper on top and rub over it with this black crayon thing to give you a nice comic-book-looking line drawing of your creation, which you can color appropriately.</p>

<p>I had totally forgotten how cool this thing is. My boy and I had a blast making superheroes, monsters, and freaky combinations of both. I loved listening to him think out loud while he decided which head he'd stick with which body and legs.</p>

<p>His best one used the three-eyed alien head with the Frankenstein-monster's torso, and the spindly little alien legs with the tail. It's on a planetscape background with one of those old-style upright sci-fi rockets parked behind it. He still has problems coloring in the lines, but does pretty well for his age I guess -- he used mostly greens and purple. He wanted some help coloring in the eyes, so I made them a bright yellow. The thing looks great now up on the wall in his room, staring back at you with those three big ol' lamplike eyes.</p>

<p>Man, they just don't make toys like that anymore.</p>]]>
           </body>
           <title>
               <![CDATA[Mighty Men & Monster Maker]]>
           </title>
           <publishedAt>2006-09-24T21:34:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-09-24-mighty-men-monster-maker</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Linked from Reddit -- bask in the <a href="http://developer.yahoo.com/ruby/">warmth of the Ruby love</a> from the guys at Yahoo. Lots of links to other places, but also has some actual content like <a href="http://developer.yahoo.com/ruby/ruby-rest.html">how to make REST calls to the Yahoo Web service with Ruby</a>.</p>]]>
           </body>
           <title>
               <![CDATA[Yahoo Ruby Developer Center]]>
           </title>
           <publishedAt>2006-09-22T16:36:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-09-22-yahoo-ruby-developer-center</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Some of it might be a little hyperbolic, but it's nice to see a post about <a href="http://steve-yegge.blogspot.com/2006/09/bloggers-block-3-dreaming-in-browser.html">what Steve Yegge's been up to lately</a>. Settle down with a drink for this one -- Stevey's blog posts are not short.</p>]]>
           </body>
           <title>
               <![CDATA[Steve Yegge on programming for the browser]]>
           </title>
           <publishedAt>2006-09-21T23:06:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-09-21-steve-yegge-on-programming-for-the-browser</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>During a conversation with a Cosmo contributor, Jeremy Epstein, about the profusion of background graphic images used for the fancy gradients in Cosmo's calendar-event lozenges, he suggested the idea of transparent PNGs over a background color as a way to reduce the number of graphics we'd need.</p>

<p>As it turns out this works swimmingly on all our supported browsers ... except IE6, of course. You can get some basic PNG transparency in IE using the <code>AlphaImageLoader</code></pre> hack, but it causes some <a href="http://www.satzansatz.de/cssd/tmp/alphatransparency.html">ugly z-index isssues</a> -- the <code>div</code></pre> with the PNG background acts kind of like the form <code>select</code></pre> element does in IE, floating to the top of stuff that should actually be in front of it.</p>

<p>You can get around in theory that by specifying z-indexes for the elements involved, but in Cosmo we're already making extensive use of z-index on those elements for the drag-and-drop of the lozenges, and it's only going to be more complicated once we start to implement calendar overlay.</p>

<p>So rather than continuing to be an old-IE-enabler, we decided that flat background colors for the event lozenges were fine and dandy for IE6, thank you very much. IE6 truly is the "new Netscape 4."</p>

<p>And I'm happy to note that after endless security downloads and updates to a fresh WinXP virtual machine, I have done an upgrade to IE7, which has actual transparent PNG support -- and it works fine there. The lozenge gradients and the Cosmo UI in general look great. Not so much the IE7 UI -- where the hell did all my menus go?</p>

<p>The nice thing about using these PNG gradient backgrounds is that now we can generate a number of different calendar color palettes from a single hue value, and not have to have a profusion of different graphics to go with each one.</p>

<p>Since we're using Dojo in Cosmo, I had a quick look and -- sure enough -- Dojo had some basic color conversion code living at <code>dojo.gfx.color</code></pre>. Since the function for converting HSV to RBG values was using a non-standard 0-255 scale for all the input values, I sat down and hammered out a patch that would let me input values in the normal 360/100/100 range you see when working in the color-picker for GIMP or Photoshop.</p>

<p>The Dojo guys were kind enough to accept the patch, so now it'll be a snap to generate the color palettes for our event lozenges in the same colors as the ones used in our desktop client, Chandler. This will let us to show calendars in multiple colors, and eventually even do overlays. This is pretty exciting stuff -- the gradients look pretty sexy, and the groundwork is now there for us to do the kind of full-featured treatment we want for multiple calendars.</p>]]>
           </body>
           <title>
               <![CDATA[Transparent PNG in the Cosmo calendar UI]]>
           </title>
           <publishedAt>2006-09-20T21:44:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-09-20-transparent-png-in-the-cosmo-calendar-ui</permalink>
</article>
       <article>           <body>
               <![CDATA[<p><a href="http://chaoseffect.com/articles/2006/09/11/tim-bray-makes-markup-wrongly">Leon Spencer has a lot to say</a> about Tim Bray's posts on XML with Ruby. Oh, the humanity.</p>]]>
           </body>
           <title>
               <![CDATA[Tim Bray has some XML issues in Ruby]]>
           </title>
           <publishedAt>2006-09-12T22:37:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-09-12-tim-bray-has-some-xml-issues-in-ruby</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>The new site for <a href="http://www.ruby-lang.org/">www.ruby-lang.org</a> is finally up, and it's gorgeous. At last we have a site that's beautiful and easy-to-navigate -- much like the Ruby language is.</p>

<p>The site runs on <a href="http://radiantcms.org/">Radiant CMS</a>, which is (naturally enough) built on Rails.</p>]]>
           </body>
           <title>
               <![CDATA[The new Ruby language site]]>
           </title>
           <publishedAt>2006-09-12T00:54:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-09-12-the-new-ruby-language-site</permalink>
</article>
       <article>           <body>
               <![CDATA[<p><a href="http://mootools.net/">MooTools</a> has come up with a really smart way to address the problem of JavaScript library bloat -- give people a <a href="http://mootools.net/download/release">Web-based interface</a> to pick and choose which components they want for their download. It even lets you choose how much compression you want to use.</p>

<p>Really nicely designed interface, too.</p>]]>
           </body>
           <title>
               <![CDATA[MooTools library's Web-based download builder]]>
           </title>
           <publishedAt>2006-09-11T11:15:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-09-11-mootools-librarys-web-based-download-builder</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Instructions for getting Japanese input working in Ubuntu Breezy Badger are a bit different from the setup under Hoary Hedgehog. (I sure do look forward to this settling down one day soon -- maybe in Dapper?)</p>

<p>Thankfully the Ubuntu wiki has a <a href="https://help.ubuntu.com/community/JapaneseInputHowToInBreezy">nice, clear instruction page for Japanese input in Breezy</a> that does the trick nicely. It worked for me without a hitch, and I can toggle back and forth between normal English and Japanese input in most all apps using the normal Ctrl+Shift. It even does the swap to katakana from F7 like you'd expect if you're an old Ichitaro hand.</p>

<p>Unfortunately the change from SCIM to UIM for IME support added a new keyboard binding of Ctrl+J for toggling the input  method ('J' for 'Japanese,' right?), which was driving me bananas because that's the binding I use in Vim for jumping between splits.</p>

<p>This is one of those times I'm actually grateful for endless <a href="http://lists.freedesktop.org/archives/uim/2004-February/000161.html">tweakability</a> of Unix. You can reset the binding in your <code>.uim</code></pre> file like so:</p>

<pre><code>(define default-im-name 'anthy) ; IM-SWITCH VALUE
(define-key anthy-on-key? '("C-a" "C-A" generic-on-key?))</code></pre></pre>

<p>As easy as that, it switched the activation toggle to a key I never touch. And Ctrl+Shift still works like you'd expect. "Shiawase da na."</p>

]]>
           </body>
           <title>
               <![CDATA[Breezy Nihongo -- Japanese input in Ubuntu Breezy]]>
           </title>
           <publishedAt>2006-08-31T23:49:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-31-breezy-nihongo-japanese-input-in-ubuntu-breezy</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>My Webcast radio station, <a href="http://www.epiphanyradio.org/">EpiphanyRadio</a>, is featured in an article on <a href="http://www.associatedcontent.com/article/55345/top_free_electronic_or_electronica.html">Top Free Electronic or Electronica Internet Radio Stations</a> over at Associated Content.</p>

<p>I'm proud to note that the EpiphanyRadio stream has been 100% RIAA-free for going on four years now. It has a pretty damned decent collection of ambient downtempo groove from indie artists all around the world.</p>]]>
           </body>
           <title>
               <![CDATA[Associated Content article on EpiphanyRadio]]>
           </title>
           <publishedAt>2006-08-31T22:14:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-31-associated-content-article-on-epiphanyradio</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>We're hiring for a <a href="http://www.osafoundation.org/employment.htm#WebUIDeveloper">Web UI developer</a> position at OSAF. This is a job working on the Ajax UI for the <a href="http://cosmo.osafoundation.org/">Cosmo</a> project.</p>

<p>We are looking for someone with some serious JavaScript/DOM/CSS kung fu -- and ideally some additional expertise, in either design or client-side app architecture.</p>
]]>
           </body>
           <title>
               <![CDATA[OSAF hiring a Web UI developer]]>
           </title>
           <publishedAt>2006-08-29T16:31:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-29-osaf-hiring-a-web-ui-developer</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Nice to know what Steve is really thinking. It's <a href="http://fakesteve.blogspot.com/">The Secret Diary of Steve Jobs</a>. ("I love beautiful objects. I love creating them. Negative people upset me.")</p>
]]>
           </body>
           <title>
               <![CDATA[Fake Steve Blog]]>
           </title>
           <publishedAt>2006-08-27T23:21:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-27-fake-steve-blog</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I figure it's about time for another nice, refreshing round of English Totalitarianism. Here's another one I hear surprisingly often -- people saying 'jive' when they really mean 'jibe.'</p>

<p>'Jive' has two basic meanings. One is musical: "jazzy music or dancing." The other refers to a kind of speech: "jargony slang or glib talk." (The second meaning is likely derived from the first one -- think about how we also use 'jazz' in the second sense: "He was giving us all that 'leveraging the robustness of our customer-centric, synergistic processes' jazz.")</p>

<p>'Jibe,' on the other hand, means "to be in accord, to agree" -- as in the sentence "Let me know if that still jibes with your original idea." This of course means "Let me know if that still matches up with your original idea." (Contrast with "Let me know if that still speaks or dances in a funky way with your original idea.")</p>

<p>Just to add to the fun, I'll point out too that there's also 'gibe' (variable spelling 'jibe') which means "to taunt or tease," as well as 'jibe' (variant spelling 'gybe'), which is apparently some sort of sailing term. Hope that makes things nice and clear.</p>
]]>
           </body>
           <title>
               <![CDATA['Jibe' vs. 'jive']]>
           </title>
           <publishedAt>2006-08-25T22:03:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-25-jibe-vs-jive</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Now that I really have a look at it, I wish I'd gone to this OSCON session. <a href="http://haxe.org/">HaXe</a> is a high-level programming languaged developed by <a href="http://ncannasse.free.fr/">Nicolas Cannasse</a> aimed at use in Web-application development. According to the haXe site, it will compile to JavaScript, Flash, or to bytecode for the Neko Virtual Machine, which can be run server-side with Apache's <code>mod_neko</code></pre>.</p>

<p>I'm not particularly a fan of stuff that requires a compile step -- I'm way too much of an instant gratification junky. Doing iterative design and development of dynamic UIs leads you toward an addiction to seeing your changes <em>right now.</em> That seems to me to be one of the biggest advantages of doing your UI right there on the client, or using a scripting language on the server -- you can make major changes to your Web app super-fast to respond to customer needs.</p>

<p>But haXe does seem like a nice way to leverage the power of having a One True Way in building your Web apps -- in the flavor of <a href="http://www.openlaszlo.org/">Open Laszlo</a> or <a href="http://code.google.com/webtoolkit/">GWT</a>, or <a href="https://phobos.dev.java.net/">Phobos</a>, only with better coverage, because it's got all of three: JS, Flash, and server. (Of course GWT and Phobos don't make you learn a new language.)</p>

<p>The haXe compiler is GPL, and the libraries are BSD. The Neko runtime is LGPL.</p>]]>
           </body>
           <title>
               <![CDATA[HaXe universal programming language]]>
           </title>
           <publishedAt>2006-08-24T23:45:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-24-haxe-universal-programming-language</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I just got an e-mail yesterday from Craig Anderson at SitePoint, letting me know that one of the folks who bought my book had noticed a small deficiency with the function that handles form serialization for the example code in the book -- the mellifluously named 'formData2QueryString.' (Man, that just <em>rolls</em> off the tongue, doesn't it?) The code for this function is a also in my <a href="http://www.fleegix.org/pages/downloads">downloads section</a> here at Fleegix.org.</p>

<p>The guy wanted multi-selects -- which I have always avoided like the plague because they confuse the hell out of novice users, and annoy the hell out of advanced users when their fingers slip and deselect all those 17 different, laboriously selected options. Not that that's every happened to me. No, I'm just being an advocate for the end-user here, really.</p>

<p>In any case, Craig was cool enough to add the multi-select case himself, and was just submitting it as a patch. The only problem was that he had implemented it the way raw form data appear on the server for items with multiple values, e.g.:</p>

<pre><code>zardoz=3&zardoz=42&zardoz=2112</code></pre></pre>

<p>This was an issue because the original implementation added a little 'magic' to things with multiple values like banks of checkboxes to the values would get collapsed into a set of comma-delimited values, like this:</p>

<pre><code>zardoz=3,42,2112</code></pre></pre>

<p>There are a few different reasons you might want to do this -- for example if you don't want to have to wrangle the same query-string-parsing code for multiple-values in several different server-side programming languages.</p>

<p>However, upon reflection it seemed like the best behavior for the default is probably just to duplicate the way the browser would submit it in a normal form. Then you can always allow people to override the default behavior to get the original 'magic' behavior.</p>

<p>So, I sat down and implemented the 'unmagic' behavior for checkboxes, and added an optional parameter that allows you to pass in a JavaScript object containing formatting options. So now, if you call the function like this:</p>

<pre><code>var str = formData2QueryString(formRef);</code></pre></pre>

<p>You'll get the correct, raw form data with the multiple, redundant variable names in the string for multiple values.</p>

<p>If you call it like this:</p>

<pre><code>var str = formData2QueryString(formRef, { 'collapseMulti': true });</code></pre></pre>

<p>It will collapse the multiple values into a comma-delimited list with a single variable name in the string.</p>

<p>I also used this opportunity to add a bit of actual JSDoc-style documentation at the top, so it looks all prim and proper now. Again, the code is available <a href="http://www.fleegix.org/pages/downloads">here in the downloads section</a>. Please do let me know of any bugs that you find. Very nice work Craig, and thanks for the help.</p>
]]>
           </body>
           <title>
               <![CDATA[Multi-select for JavaScript form serialization]]>
           </title>
           <publishedAt>2006-08-24T21:54:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-24-multi-select-for-javascript-form-serialization</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>This past weekend was the <a href="http://www.slconvention.com/">Second Life Community Convention</a> in San Francsisco. I happened to be out at the OSAF office this past week, so I was lucky enough to be able to check out some of the festivities on Friday night, but missed Mitch's talk on Saturday. Mitch put up a link on <a href="http://blog.kapor.com/">his blog</a> to a <a href="http://www.3pointd.com/20060820/mitch-kapor-on-the-power-of-second-life/">really nice writeup of his talk</a> for those of us who missed it. He had a lot thought-provoking stuff to say about early adopters and SL as a 'disruptive technology.'</p>

<p>Coincidentally, there was also an <a href="http://www.freesoftwaremagazine.com/node/1713">interesting article on avatars</a> at Free Software Magazine that floated up on Digg. It talks about the interaction of identity with appearance online. Smack in the middle is a nice side-by-side of Mia Garlick from <a href="http://creativecommons.org/">Creative Commons</a> (who was once kind enough to save me from the alarm in the OSAF/CC offices when I foolishly triggered it -- that woman can sprint!) and her Second Life avatar. I didn't even know she played SL.</p>]]>
           </body>
           <title>
               <![CDATA[Second Life and avatars]]>
           </title>
           <publishedAt>2006-08-22T01:18:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-22-second-life-and-avatars</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Nothing like a nice denial-of-service to end your day. Last night at exactly 9pm CDT, my server was hit by some heavy DDOS spam siege. This site (Fleegix.org), and my Webcast radio station, <a href="http://www.epiphanyradio.org/">EpiphanyRadio</a>, are on the box -- along with a couple of other sites.</p>

<p>I still can't quite figure out if it was intended as an attack, or just a botched attempt to send spam for money-making purposes -- but the end result was a several thousand error messages for transient lookup failures filling my inbox, since poor Postfix couldn't keep up with the load. The epiphanyradio.org domain was getting hit by thousands upon thousands of messages to non-existent accounts of first and last names with three random characters in the middle (DonaldxJfWilson, ScottjDqMoore, StephencVoGonzalez, JeffreyrWpHarris, etc.) and it was pounding the box into oblivion.</p>

<p>After yanking epiphanyradio.org out of <code>virtual_mailbox_domains</code></pre> and getting the service back up and running, I did a bit of logfile crunching, and found that there were 3347 unique IP addresses sending me this stupid crap, from all over the world. I guess that's a pretty fair-sized zombie army. I can't help but think it's some pretty amazing technological prowess -- coordinating all those machines to work together that way. Too bad it's deployed in the service of something so totally reprehensible, pointless, and stupid.</p>

<p>It has slowed to a trickle tonight, but I can still see these messages coming in occasionally as I tail the logfile. Somewhere out there are a few sad, unpatched Exchange servers still churning out e-mails uselessly for these spammer idiots trying to pitch their V14gr4, stock 'tips,' or whatever to Edwardu6fHarris, and MatthewntwPhillip, and AnthonyiojLewis, and Stepheni0cYoung, and JoseeUzWright, and ...</p>]]>
           </body>
           <title>
               <![CDATA[DDOS spam attack on EpiphanyRadio]]>
           </title>
           <publishedAt>2006-08-10T23:02:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-10-ddos-spam-attack-on-epiphanyradio</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Amy Hoy's talk at OSCON 2006 reminded me of a <a href="http://www.uxmatters.com/MT/archives/000107.php">really nice study I saw on UXMatters</a> on that provides some emperical data to back up the 'common wisdom' for placement of labels for elements in Web forms.</p>

<p>The study uses eye-tracking data to measure how much eye movement and cognitive processing time was needed for three different ways of placing labels relative to their form elements.</p>

<p>From best to worst:</p>

<ol>
<li>Left-aligned labels placed above the form element. "Placing a label right over its input field permitted users to capture both elements with a single eye movement."</li>
<li>Right-aligned labels placed to the left of the form element. "The right alignment of the labels reduced the overall number of fixations by nearly half, showing that this layout greatly reduced the cognitive load required for users to complete the task. Also, the form completion times were cut nearly in half."</li>
<li>Left-aligned labels placed to the left of the form element. "Excessive distances between some labels and their input fields forced users unnecessarily to take more time to interact visually with the form."</li>
</ol>

<p>So, this is some objective data that shows that putting labels in a left-aligned position right above their elements really does allow users to process the form the most efficiently.</p> 

<p>Of course design is all about compromise, so you should also consider whether that's going to make your form prohibitively long vertically. Design, design -- always with the tradeoff thing.</p>
]]>
           </body>
           <title>
               <![CDATA[Label placement with Web form elements]]>
           </title>
           <publishedAt>2006-08-06T00:56:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-06-label-placement-with-web-form-elements</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Our presentation for <a href="http://conferences.oreillynet.com/os2006/">OSCON 2006</a> on Cosmo/Scooby went fairly well it seems, especially given how much content we were trying to stuff into such a short amount of time. Kevin Yank over at <a href="http://www.sitepoint.com">SitePoint</a> did some really nice <a href="http://www.sitepoint.com/blogs/2006/07/29/oscon-2006-cosmo-and-scooby-standards-based-open-source-calendaring/">reporting on the presentation</a> for the SitePoint blogs.</p>

<p>Here's a quick rundown of the stuff that stuck in my mind from the tutorials and sessions.</p>

<p><strong>Rails Guidebook (tutorial) (Dave Thomas, Mike Clark)</strong></p>

<p>This was in one of the larger rooms, and was (predictably) quite full. It was mostly a solid, basic, step-by-step intro to Rails -- naturally including the standard Rails demo of rapidly building a basic application.</p>

<p>There were also some bits beyond the basics that were pretty interesting:</p>

<ul>
<li>Migrations -- a procedural way (in Ruby code, natch) to create and modify your database schema. I prefer sticking with the native database tools like <code>pg_dump</code></pre>, but Migrations likely work better for a team, or if you don't want to be tied to a specific DB.</li>
<li>Model finder methods -- seeing some of the different ways to do it is helpful for someone like me who tends to use <code>find_by_sql</code></pre> as a crutch.</li>
<li>Many-to-many associations -- a new way to manage this called 'through associations' that lets you hang metadata about the association on it</li>
<li>Generating XML -- using builder templates with 'rxml' files</li>
<li>Simply RESTful -- routing plugin that maps REST verbs to the normal Rails CRUD actions.</li>
</ul>

<p><em>(No slides online.)</em></p>

<p><strong>Testing Web Apps (tutorial) (John Paul Ashenfelter)</strong></p>

<p>Covered both functional testing with Selenium, and load testing with Grinder.</p>

<ul>
<li><a href="http://wiki.openqa.org/display/SEL/Home">Selenium</a> is a full-fledged testing framework for Web applications that's free and open source (FOSS), and written in JavaScript and HTML. It was pretty cool to see his build script launch Firefox automatically and whiz through the tests.</li>

<li><a href="http://grinder.sourceforge.net/">Grinder</a> is a free Java-based load tester. You can install and run it on multiple machines, and it can coordinate the tests and record the results in one central location. It also lets you
record tests using a browser rather than scripting them by hand.</li>
</ul>

<p>Slides are <a href="http://transitionpoint.com/downloads/oscon2006.zip">available online here</a>.</p>

<p><strong>Big Bad PostgreSQL (Theo Schlossnagle)</strong></p>

<p>This talk was on converting a large (over 3 terabytes, largest table is 1.8 billion rows) data warehouse from Oracle 8i to PostgreSQL. They chose Postgres over MySQL because Postgres has had the kind of advanced features they needed for a very long time.</p>

<p>They needed (and were able to hack PostgreSQL to get) the following features:</p>

<ul>
<li>Data partitioning (spreading tables over multiple drives)</li>
<li>Large selects (50-million-row return sets, over 100GB</li>
of data)
<li>Incremental COMMITs for really, really long queries</li>
<li>Replication</li>
</ul>

<p>The conversion saved them $500,000 USD in licensing costs (on $100,000 of extra labor costs, still a decent chunk of change in savings).</p>

<p>Slides are <a href="http://www.lethargy.org/~jesus/exit.php?url_id=91&entry_id=66">available online here</a>.</p>

<p><strong>Ajax Optimization Techniques (Kevin Henrikson)</strong></p>

<p>Covered the 'three Cs' of Ajax optimization:</p>

<ol>
<li>Combine: Put all your JavaScript and CSS files together into a single file (or a few files) instead of loading 12 or 15 different files.</li>
<li>Compress: Use something like Crockford's <a href="http://www.crockford.com/javascript/jsmin.html">JSMin</a> or Dojo's <a href="http://alex.dojotoolkit.org/shrinksafe/">ShrinkSafe</a> on your JavaScript, and gzip your JS and CSS files, or use <a href="http://sourceforge.net/projects/mod-gzip/">mod_gzip</a> or <a href="http://httpd.apache.org/docs/2.0/mod/mod_deflate.html">mod_deflate</a>.</li>
<li>Cache: Cut down on the number of requests to the server for static images and frequently used resources.</li>
</ol>

<p>Slides are <a href="http://downloads.zimbra.com/blog_pics/OSCON_2006_AJAX_Optimization_Henrikson.pdf">available online here</a>.</p>

<p><strong>TimeTravel Tables in PostgreSQL (A. Elein Mustain)</strong></p>

<p>Showed how to use timestamps to keep an audit trail of all changes in your DB. With this technique, you never actually delete records, you merely give them an end date. Multiple copies of a record (again, with timestamps for each one) also allow you to track edits. (This is a fairly normal approach, especially in 'validated' environments, or industries which are regulated by the government.)</p>

<p>The value of using Postgres here is in the advanced features like triggers that you can use with your deletes and updates to offload the work needed to maintain this 'time travel' system -- rather than forcing your app logic to keep up with all of it. </p>

<p>You can also use PostgreSQL's views to query the database for only the current data, or write procedural functions to query the state of the database at a particular point in time in the past.</p>

<p>Slides are <a href="http://www.varlena.com/GeneralBits/Tidbits/tt.pdf">available online here</a>.</p>

<p><strong>When Interface Design Attacks (Amy Hoy)</strong></p>

<p>I was amazed to see how packed this session was. They propped the doors, and people were actually standing around outside the door trying to listen. It was really good to see that so many developers are looking for a way to make
their interfaces more usable.</p>

<p>Slides are <a href="http://amyhoy-presentations.s3.amazonaws.com/when_interface_design_attacks.pdf.zip">available online here</a>.</p>

<p><strong>Web Heresies: The Seaside Framework (Avi Bryant)</strong></p>

<p>The <a href="http://www.seaside.st/">Seaside Framework</a> is an interesting departure from other mainstream Web-app frameworks in a number of ways:</p>

<ul>
<li>It's written in the <a href="http://en.wikipedia.org/wiki/Smalltalk">Smalltalk</a> language.</li>

<li>It blows off traditional MVC templating in favor of generating markup programmatically directly in the application logic.</li>

<li>It keeps all session state in memory instead of serializing it -- which means you can store callback functions and closures in the session, and even use continuations (at the cost of requiring sticky sessions, lots of memory, and inability to recover session data in the event of server failure).</li>
</ul>

<p><em>(No slides online.)</em></p>
]]>
           </body>
           <title>
               <![CDATA[OSCON 2006]]>
           </title>
           <publishedAt>2006-08-04T14:01:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-04-oscon-2006</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I've been invited to be an 'occasional blogger' over at the <a href="http://www.sitepoint.com/blogs/">SitePoint Blogs</a>. I'll be posting stuff about Web tech mostly, but also probably some on design and open source as well.</p>]]>
           </body>
           <title>
               <![CDATA[Blogging at SitePoint]]>
           </title>
           <publishedAt>2006-08-04T02:04:12.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-04-blogging-at-sitepoint</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Joel Spolsky talks about how handy those <a href="http://www.joelonsoftware.com/items/2006/08/01.html">first-class functions</a> can be. Kind of eerie seeing Joel putting up example code in JavaScript. What is this world coming to?</p>

<p>Nice shout-out to Steve Yegge at the end.</p>]]>
           </body>
           <title>
               <![CDATA[Joel on JavaScript]]>
           </title>
           <publishedAt>2006-08-01T22:38:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-08-01-joel-on-javascript</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>My colleague Lisa Dusseault just sent an <a href="http://lists.osafoundation.org/pipermail/scooby-dev/2006-July/000723.html">e-mail to the scooby-dev mailing list</a> saying that JSON is now an IETF standard. Check out RFC 4627:</p>

<p><a href="http://www.rfc-editor.org/rfc/rfc4627.txt">http://www.rfc-editor.org/rfc/rfc4627.txt</a></p>

<p>This is great news for all the Web devs trying to explain to the <a href="http://en.wikipedia.org/wiki/Pointy_Haired_Boss">PHB</a> why using JSON is better than jumping through the hoops needed to deserialize XML data for their JavaScript code (much less do it quickly and reliably).</p>

<p>Sure, I know -- without 'XML,' we wouldn't have that cool 'X' in 'Ajax,' would we? Actually, Jesse James Garrett -- the guy who coined the phrase and stuff -- <a href="http://www.ok-cancel.com/archives/article/2005/09/why-ajax-matters-now.html">doesn't  write it as an acronym</a>, and has said in talks that he doesn't consider it one (the <a href="http://www.adaptivepath.com/publications/essays/archives/000385.php">original Ajax paper</a> describes it as 'shorthand for').</p>

<p>Right, so 'Ajax' really is just a snappy, meaningless term -- like a semantic <a href="http://en.wikipedia.org/wiki/Rorschach_inkblot_test">Rorschach test</a> that different people can all use <a href="http://www.ok-cancel.com/comic/105.html">to mean whatever they want</a>.</p>

<p>So you can keep that cool letter 'X.' (Please don't put on your Helm of Pedantic Might and call it 'Ajaj.') And more importantly, you can use a super-simple, <em>standards-based</em> way to serialize your data that really Just Works&#8482; with JavaScript.</p>]]>
           </body>
           <title>
               <![CDATA[JSON is a Web standard -- RFC 4627]]>
           </title>
           <publishedAt>2006-07-31T23:11:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-07-31-json-is-a-web-standard-rfc-4627</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I'm in Portland, Oregon this week for O'Reilly's <a href="http://conferences.oreillynet.com/os2006/">OSCON</a>. I'll be presenting a bit about Scooby's Web UI on Friday.</p>

<p>Over at the Sztywny Blog (wow, someone with a last name as hard-to-spell as mine), there's a nice post where the guy has e-mailed a bunch of questions to various well-known programmers -- and most of them actually are nice enough to answer.</p>

<p>Buried in the middle of this thing is an interesting statement from Steve Yegge, someone you might know from <a href="http://www.cabochon.com/~stevey/blog-rants/">Stevey's Drunken Blog Rants</a>.</p>

<blockquote>I think web application programming is gradually going to become the most important client-side programming out there. I think it will mostly obsolete all other client-side toolkits: GTK, Java Swing/SWT, Qt, and of course all the platform-specific ones like Cocoa and Win32/MFC/etc.</blockquote>

<p>He points out that the browser still has a way to go before it gets there, but then adds, "I've finally decided to switch all my own app development over to browser-based programming from now on." And a bit later, in the answer to another question, Steve also writes, "I do happen to have 3 months (part-time), and I'm spending it learning Dojo (http://dojotoolkit.org) and advanced AJAX and DHTML."</p>

<p>The whole blog post is a good read -- cool to see the different personalities in the responses to all the questions. But Steve's little bomb is probably the most interesting thing there.</p>]]>
           </body>
           <title>
               <![CDATA[Steve Yegge: Web apps will 'win']]>
           </title>
           <publishedAt>2006-07-24T01:32:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-07-24-steve-yegge-web-apps-will-win</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Another interesting couple of salvoes in the ongoing "is not, is too" argument of whether or not Real Web Developers have to know JavaScript, or if it's okay for them to rely on server-side 'helpers' and JS libraries.</p>

<p>Over at DOM Scripting, in a post that seems to be aimed primarily at guys on the design side of the continuum, Jeremy Keith encourages people to <a href="http://domscripting.com/blog/display/78">start picking up JavaScript</a> because it's just plain necessary to their jobs these days -- "Learning JavaScript is something that you can postpone, but you really can't avoid," he says.</p>

<p>He also links to a nice rant by James Bennet about <a href="http://www.b-list.org/weblog/2006/07/02/django-and-ajax">the state of Ajax support in the Django Web development framework.</a> James's post seems more aimed at the server-side developer side of the equation, but he's also firmly in the 'learn JavaScript, dammit' camp, saying he doesn't think that Django needs server-side 'Ajax helpers' that generate JS.</p>

<p>He uses some even stronger rhetoric:</p>

<blockquote>In 2006, if you call yourself a "web developer" you have absolutely no excuse for not knowing JavaScript. And if you don't know JavaScript, you have absolutely no right to call yourself a "web developer".</blockquote>

<p>Pretty strong language (and pretty tailor-made for getting a nice, heated discussion going in your comments).</p>

<p>I'd firmly agree that as Ajax and client-side development become more important, you're putting yourself at a serious disadvantage if you don't develop a decent familiarity with JavaScript. To me it just seems like one the basic tools used to create a properly interactive Web application.</p>

<p>On the other hand, if your needs are really, really modest, you might be able to get by with relying solely on 'helpers' or copy-pasted code from the how-to for some JS toolkit. Say you're a sys-admin who just wants a bit of drag-and-drop fanciness in your Web console app (and you don't care if it's unusably slow or maybe unreliable in some browsers) -- you might get by fine with stuff from the Scriptaculous effects library, or using whatever RJS helpers Rails offers for that.</p>

<p>However people who refuse to take those training wheels off are limiting themselves to a pretty tiny swath of what client-side JS code can do. People who actually know JavaScript and code their own will be able to produce vastly more powerful interfaces for their apps.</p>

<p>And I will also (uncharitably) submit that if you want all the nice benefits that JavaScript-driven Ajax can provide you, but you somehow find JS so unbearably icky that you just can't bring yourself to touch it, you <em>totally deserve what you get</em> when something in all those layers abstracting away the JavaScript 'ickiness' breaks.</p>

<p>The toolkits actually written in JS are at least developed by JavaScript hackers who know what they're doing, so even though they may be <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">leaky abstractions</a>, you can count on them to get stuff mostly right. On the other hand, knowing what I know about JavaScript in general, and more specifically about the infinitude of opportunities for cross-browser weirdnesses in client-side code, I'm naturally a little suspicious of anything that purports to be able to transform a server-side language like <a href="http://code.google.com/webtoolkit/">Java</a> or <a href="http://dev.rubyonrails.org/changeset/3078">Ruby</a> into perfectly working client-side JavaScript.<p>

<p>I'll also cop to the fact that some of this suspicion comes from being a second-language speaker of Japanese. I'll never be a native speaker of course, but I'm pretty comfortable that most of the time what I'm saying is grammatically and idiomatically correct. Speaking another language gives you a bit of insight into how hard it really is to translate one <em>theoretically</em> equivalent thing into another.</p>

<p>Whenever I think of GWT, I think of the gibberish <a href="http://babelfish.altavista.com">BabelFish-translated</a> e-mail messages in English I get occasionally from my mother-in-law in Japan. (I have no idea why she does this.) Because I can guess what the original Japanese probably was, I can actually follow these messages for the most part, but some parts literally make no sense whatsoever. So the idea of this flawless, magical conversion ("No more spending 90% of your time on browser incompatibilities! We solve that for you, like magic! No ugly JavaScript necessary!!!") -- still seems pretty much in the category of sci-fi conceits like the <a href="http://en.wikipedia.org/wiki/Universal_translator">universal translator</a> or <a href="http://www.scifi.com/farscape/notes/translator.html">translator microbes</a>.</p>

<p>Actually I'm sure these "helpers" probably work really well within a fairly narrow band of functionality. Just like those computerized translation devices our soldiers are carrying around Baghdad are really good at spitting out preset phrases like "put your hands in the air" or "stop where you are." But if they wanted to expand that dialog into a discussion of Arabic history or art, they'd be SOL.</p>

<p>So if you have any intention of doing a seriously interactive Ajax-style browser-based app, you're going to have much greater power, and much larger range of possibilities open to you if you take the time to become fluent in the actual language of the browser. And despite what the inevitable pompous language bigots in #ruby-lang (for example) say, JavaScript is quite a nice language -- the syntax is not nearly as clean as say, Ruby or Python, but it's not at all icky and is actually pretty damned fun.</p>
]]>
           </body>
           <title>
               <![CDATA[Speak JavaScript or die]]>
           </title>
           <publishedAt>2006-07-20T22:24:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-07-20-speak-javascript-or-die</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Time to let out my innner English Fascist. Yeah, sure, I'm a programmer now, but I have a degree in English Lit, and I spent three years <a href="http://www.jetprogramme.org/">teaching English in the public schools in Japan</a>. I may have an unhealthy obsession with English minutiae, but at least I come by it honestly.</p>

<p>I'm still amazed by the number of times I hear people in meetings saying 'flush out' when they really mean 'flesh out.' In these meetings, the people are referring to some sort of rough idea or plan, where they need more details before they can begin taking action.</p>

<p>'Flush out' -- in a general context -- means to remove something undesirable from an enclosed space using a stream of water (e.g., flush out a clogged pipe). In the context of hunting, 'flush out' means to scare the quarry out of whatever place it's hiding so you can shoot or pursue it.</p>

<p>In the case of a vague or nebulous plan, the correct phrase is 'flesh out'  -- i.e., the rough plan is just a skeleton that needs actual 'flesh' on it before you can take action.</p>

]]>
           </body>
           <title>
               <![CDATA['Flesh out' vs. 'flush out']]>
           </title>
           <publishedAt>2006-07-16T22:33:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-07-16-flesh-out-vs-flush-out</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I was playing around with styled buttons and text inputs for forms yesterday, and ran into an interesting (yeah, we all know what that means) CSS issue.</p>

<p>A <code>text</code></pre> input and <code>button</code></pre> input with identical styling (it was something like <code>height:24px; border:1px solid #aaaaaa; padding:2px;</code></pre>) actually display with totally different heights -- and vertically out of alignment to boot. And oddly, it was broken in pretty much the same way in both Firefox 1.5 and IE6.</code></pre></p>

<p>I made the unfortunate mistake of poking my head into #css on Freenode to ask if anyone else had seen this. And after placating the silly punks in there who think they're participants in some sort of feudal tribute system, I found that nobody had the foggiest clue what might be causing it.</p>

<p>After doing a bit of poking around with Firebug's DOM inspector, I finally realized what was going on. Once I knew what to Google on, I found that it was a <a href="http://www.quirksmode.org/css/tests/mozie_button.html">documented bug with both Firefox and IE</a>.</p>

<p>Even in Standards Compliant mode, <code>button</code></pre> inputs use the old box model where the style's <code>height</code></pre> and <code>width</code></pre> reflect the size of the container, not the content in the container. Of course, <code>submit</code></pre> (being kissin' cousins with <code>button</code></pre>) inputs also suffer from this same malady. Hooray!</p>

<p>The text input uses the correct W3C box model, so they naturally don't match up.</p>

<p>I would love to know why it does this -- it's broken the exact same way in both creaky ol' IE and modern Firefox. Honestly sometimes with this stuff you feel like you're playing a game of <a href="http://en.wikipedia.org/wiki/Fizzbin">Fizzbin</a> or something.</p>

<p>"Form element? In IE? What is it? Oh, a <code>select</code></pre> input. No, you can't put anything in front of that. It's a native Windows control. What? A <code>radio</code></pre> button? Nope, not with DOM methods. Ah, a <code>button</code></pre>. Oh, okay, in Mozilla. Well, you can, but it uses the old box model. Except at night, when you want a queen and a four."</p>
]]>
           </body>
           <title>
               <![CDATA[Form input buttons and the box model]]>
           </title>
           <publishedAt>2006-07-14T21:42:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-07-14-form-input-buttons-and-the-box-model</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Now even <a href="http://radar.oreilly.com/archives/2006/06/ubuntu_linux_a_threat_to_mac_o.html">Tim O'Reilly has chimed in</a> on the subject of the announcements by <a href="http://diveintomark.org/archives/2006/06/02/when-the-bough-breaks">Mark Pilgrim</a> and <a href="http://www.boingboing.net/2006/06/29/mark_pilgrims_list_o.html">Cory Doctorow</a> that they are switching to Ubuntu Linux.</p>

<p>All I have to add is that the story of a prominent Mac user switching to Linux after frustrations with lost data and proprietary formats <a href="http://artlung.com/smorgasborg/C_R_Y_P_T_O_N_O_M_I_C_O_N.shtml">is a fairly familiar one</a>.</p>

<blockquote>Hacker with bullhorn: "Save your money! Accept one of our free tanks! It is invulnerable, and can drive across rocks and swamps at ninety miles an hour while getting a hundred miles to the gallon!"</blockquote>

<p>It did seem fairly obvious that OS X's Unixey goodness would take a bit of wind out of the sails of Linux on the desktop, but I figured it'd continue to move forward -- and Ubuntu seems to get closer with each release to that threshold of actual usability for normal people.</p>

<p>Apple seems to have learned how to compete against "good enough, but cheaper." Actually, it might be the Windows guys who should be concerned -- you don't get much cheaper than "accept one of our free, invulnerable tanks," and Ubuntu is making that high-tech super-tank easier and easier to drive.</p>

]]>
           </body>
           <title>
               <![CDATA[Mac switchers -- to Ubuntu]]>
           </title>
           <publishedAt>2006-07-04T23:50:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-07-04-mac-switchers-to-ubuntu</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I can't stop giggling. I was checking out BoingBoing and noticed <a href="http://www.boingboing.net/2006/07/02/japanese_tv_nets_sla.html">this post</a> that talks about NHK getting its collective panties in a wad about a raft of <a href="http://www.youtube.com/results?search=SPOO">parody videos on YouTube</a> involving a character from one of its shows. The videos lampoon a seriously unfortunate drawing of the character Spoo done by one of the main actors, Shoko-Oneesan (Miss Shoko) on a children's show called "Okaasan to Issho" ("With Mother").</p>

<p>The funny thing here for me is that my kids watch this show every morning on satellite TV (we're trying to get them as much exposure as we can to Japanese while they're small), and my wife was telling me about this little incident with the drawing a few weeks ago. She said she was laughing so hard she was crying -- as you can see in the <a href="http://www.youtube.com/watch?v=gzYV4bMfyCo&search=SPOO">original video</a>, Shoko-Oneesan's drawing partner can't keep a straight face looking at her 'drawing.' My wife said the dialog afterward just made it even funnier. "Wow, you drew such a great picture!" "Good job!" "I'm  glad I was able to draw it."</p>]]>
           </body>
           <title>
               <![CDATA[Spoo on YouTube]]>
           </title>
           <publishedAt>2006-07-03T22:28:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-07-03-spoo-on-youtube</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Sometimes when my little boys are riding that fine line between the normal level of screaming and hyperactivity (i.e., Monkey House at the Zoo Level) and and completely out of control (i.e, Total Intergalactic Destruction Level), it helps to pull one out of the fray and do something a little unexepected.</p>

<p>So today I snagged our oldest (who's almost four), stood him up on top of the counter, and asked him to select the background soundtrack for lunchtime. (Today I made scrambled eggs with toast for lunch -- I was trying to give my wife a bit of a break, since it looked like steam was about to start coming out of her ears.)</p>

<p>Of course he pretty much just picks at random, and what we ended up with was the Verve compilation of Wes Mongomery tracks called <a href="http://www.amazon.com/gp/product/B0000046T9/">Jazz 'Round Midnight</a>. Kind of a weird choice for a Sunday lunch at home with the accompanying screams, giggling, and loud THWACK sounds you get with a three boys under the age of four cavorting around the first floor of our house, which is basically a large, open area with ceramic floor tile.</p>

<p>When they finally settled down to eat, the smokey-lounge ambience of the music did kind of provide an interesting counterpoint to the egg-festooned faces, milk guzzling, and sprinklings of toast crumbs. And the jazz cool did seem to calm them down a tad. Or maybe that's just wishful thinking.</p>]]>
           </body>
           <title>
               <![CDATA[Scrambled eggs 'round midnight]]>
           </title>
           <publishedAt>2006-07-03T00:20:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-07-03-scrambled-eggs-round-midnight</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I kind of like how the acronym for the title of my book starts with 'BYO' -- kind of makes it sound like you might start doing keg stands a few chapters into it.</p>

<p>It's only been out a week, and there's already something I'm noticing in code I'm writing now that would have made for cleaner example code in the book.</p>

<p>Because of how JavaScript uses <a href="http://foldoc.org/?lexical+scope">lexical scope</a>, a lot of the places I used the local variable <code>self</code></pre> multiple times as an alias for 'the current object' (coding around the loss-of-scope annoyance you get with XHR, <code>setTimeout</code></pre>, and friends), I could have just used a single 'private member' <code>self</code></pre> inside the constructor function.</p>

<p>In the book I generally tried to take the easiest approach with the loss-of-scope stuff, so I made heavy use of the Singleton pattern in the example code. So, there's a lot of code that looks like this:</p>

<pre><code>var FlashGordon = new function() {
    this.attack = false;
    this.rocketCycle = 'ride';

    function rideRocketCycle() {
        var self = FlashGordon;
        if (self.rocketCycle == 'ride') {
            // Do rocket-cycle-riding stuff
        }
    }
    this.attackMing = function() {
        var self = FlashGordon;
        self.attack = true;
        // Do stuff to attack Ming the Merciless
    }
    this.saveUniverse = function() {
        var self = FlashGordon;
        if (self.attack) {
            // Do stuff to save the universe
        }
    }
}</code></pre></pre>

<p>That could be made a bit less verbose like this:</p>

<pre><code>var FlashGordon = new function() {
    
    var self = this;
    
    this.attack = false;
    this.rocketCycle = 'ride';
    this.save = false;

    function rideRocketCycle() {
        if (self.rocketCycle == 'ride') {
            // Do rocket-cycle-riding stuff
        }
    }
    this.attackMing = function() {
        self.attack = true;
        // Do stuff to attack Ming the Merciless
    }
    this.saveUniverse = function() {
        if (self.attack) {
            // Do stuff to save the universe
        }
    }
}</code></pre></pre>

<p>Note that it's also a handy way to give your private methods access to the object as well. I would have noticed this earlier if I'd paid better attention to <a href="http://www.crockford.com/javascript/private.html">Professor Crockford</a>.</p>]]>
           </body>
           <title>
               <![CDATA[BYOAWA Errata/Comments, Part 1]]>
           </title>
           <publishedAt>2006-06-29T23:22:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-06-29-byoawa-errata-comments-part-1</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Trying to get Rails up and running on my laptop under Ubuntu Breezy Badger, I ran into some serious irritation. Rails is fairly picky about which version of Ruby it will work with -- it requires either 1.8.2 or 1.8.4. Of course Breezy ships with Ruby 1.8.3. Of course.</p>

<p>I've always compiled Ruby from source anyway, but this time around I had been thinking I'd try doing things the simple way, and just use all the distro packages. But with the versioning weirdness, it turned out to be not so simple after all -- the only way to make things work that I could figure out was to install the Ruby packages for Dapper Drake, which of course b0rks your ability to do a normal <code>apt-get</code></pre> for everything else.</p>

<p>I actually even tried installing Dapper, but since it doesn't seem quite 'baked' yet (there was the little matter of my laptop not booting with the Dapper kernel), going back to building from source on Breezy seemed the most sane option for me. Here are the notes I took during the process. I they help somebody avoid some of the holes I stepped in. Do all this stuff as the superuser, natch.</p>

<p>First, since we're going to be building stuff from source, you have to install a compiler. I remember when I started using Ubuntu after coming from Gentoo I was aghast to see it came with nothing to compile code. We'll rectify that situation by installing gcc and friends:</p>

<pre><code>apt-get install autoconf autotools-dev binutils 
gcc gcc-4.0 libc6-dev make</code></pre></pre>

<p>Next, since this was a brand-new install of Breezy, I had to install Apache:</p>

<pre><code>apt-get install apache2 apache2-threaded-dev</code></pre></pre>

<p>Since later I intend to build mod_ruby from source, I also installed the <code>apache2-threaded-dev</code></pre> package. (In another post I'll put up how to build mod_ruby, eruby, and Ruby's DBI for database access.) Also, Rails needs mod_rewrite. Ubuntu installs it with Apache, but does not enable it. Enable it by creating a symlink for <code>/etc/apache2/mods-available/rewrite.load</code></pre> in <code>/etc/apache2/mods-enabled</code></pre>.</p>

<p>Next, for the database. I use PostgreSQL, so I installed that, along with its dev packages so I can build the Ruby Postgres support. You'll see that step at the very end of the process. Install Postgres like so:</p>

<pre><code>apt-get install postgresql postgresql-dev libpq-dev</code></pre></pre>

<p>To make Postgres work with your Ruby Web app, you have to allow conections to it over TCP/IP. You do that by setting <code>'tcpip_socket = true</code></pre>' in <code>/etc/postgresql/7.4/main/postgresql.conf</code></pre>. To make things less annoying, I also loosen the vice-like grip of Postgres security (it's a dev box, on an internal network) by setting the auth METHOD to 'trust' (from 'ident sameuser' or 'md5') in <code>/etc/postgresql/7.4/main/pg_hba.conf</code></pre>. That way I can connect with the username 'postgres' and no password.</p>

<p>Next, since I'm not keen on using slow CGI or WEBrick to do my dev work, I installed fcgid (an alternative to fastcgi) to run my Rails app in Apache:</p>

<pre><code>apt-get install libapache2-mod-fcgid libfcgi-dev</code></pre></pre>

<p>Note that I also installed the <code>libfcgi-dev</code></pre> package so I can install the Ruby bindings for FastCGI. I'll be installing that as a Ruby gem later. Enable fcgid by creating symlinks for <code>/etc/apache2/mods-available/fcgid.conf</code></pre> and <code>/etc/apache2/mods-available/fcgid.load</code></pre> in <code>/etc/apache2/mods-enabled</code></pre>.</p>

<p>Now it's time to start building stuff from source. We'll start with Ruby itself. By default it will try to stick itself in <code>/usr/local</code></pre>. The distro packages I've seen on Linux normally place it in <code>/usr</code></pre>, and that's where I like to have it too, so I build it like this:

<pre><code>cd ruby-1.8.4
./configure --prefix=/usr
make
make install
</code></pre></pre>

<p>Next, I had to install ruby-zlib, which is needed by rubygems, but not included in the core Ruby distro. I've <a href="http://www.fleegix.org/articles/2005/09/09/finally-typo">posted on this irritation previously</a>. Build ruby-zlib like this:</p>

<pre><code>cd ruby-zlib-0.6.0
ruby extconf.rb
make
make install</code></pre></pre>

Next, to build rubygems, which is what we'll actually use to install Rails:

<pre><code>cd rubygems-0.8.11
ruby setup.rb</code></pre></pre>

<p>Once rubygems is set up, you can finally install Rails itself:</p>

<pre><code>gem install rails --include-dependencies</code></pre></pre>

<p>Next is the Ruby FastCGI bindings:</p>

<pre><code>gem install fcgi</code></pre></pre>

<p>The very last thing to do is to build Ruby support for Postgresql, so your Rails app can talk to the database:</p>

<pre><code>cd ruby-postgres-0.7.1
ruby extconf.rb  
--with-pgsql-include-dir=/usr/include/postgresql  
--with-pgsql-lib-dir=/usr/lib/postgresql
make
make install</code></pre></pre>

<p>Ubuntu doesn't put the Postgres libraries and development header files where the ruby-postgres default config expects to find them, so you have to tell it in the configuration step.</p>

<p>The very last thing you'll need to do to get your Rails app up and running is to tell it to expect fcgid instead of fastcgi. Change the line in <code>yourapp/public/.htaccess</code></pre> that looks like this:</p>

<pre><code>AddHandler fastcgi-script .fcgi</code></pre></pre>

And make it look like this:

<pre><code>AddHandler fcgid-script .fcgi</code></pre></pre>

<p>Of course you'll also want to make sure the last line in the .htaccess file points everything to <code>dispatch.fcgi</code></pre> rather than <code>dispatch.cgi</code></pre>.</p>

<p>I would love feedback on this how-to -- is there a better way to do any of this?</p>]]>
           </body>
           <title>
               <![CDATA[Rails with Ruby from source on Ubuntu Breezy]]>
           </title>
           <publishedAt>2006-06-21T23:04:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-06-21-ruby-on-rails-from-source-on-ubuntu-breezy</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Holy crap, does this stuff taste sweet.</p>

<p>After playing around with Rails for awhile now, I can understand why it's gotten so over-hyped. As a guy who's been working on different types of Web apps for a long time now (and of course also developed various one-off frameworks in ASP/ASP.net, PHP, and Ruby for building those apps), it's pretty mind-bending to work with something that takes away this much of the annoying, repetitive grunt work you normally have to do to produce a working app.</p>

<p>And it actually does do it with the aplomb I hoped to see from something built on a language foundation as elegant, flexible, and intuitive as Ruby.</p>]]>
           </body>
           <title>
               <![CDATA[Tasty Ruby-on-Rails Kool Aid]]>
           </title>
           <publishedAt>2006-06-17T21:13:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-06-17-tasty-ruby-on-rails-kool-aid</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>According to the nice folks at <a href="http://www.sitepoint.com">SitePoint</a>, my book, <a href="http://www.amazon.com/gp/product/0975841947">Build Your Own Ajax Web Applications</a> (AKA the 'jigsaw book'),  will be launching at the beginning of next week.</p>

<p>A quick note -- SitePoint has agreed to release all the source code for the book under the <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License, Version 2.0</a>. I am certainly hoping the code is educational, but it would be nice if people can find other uses for it as well.</p>]]>
           </body>
           <title>
               <![CDATA[Ajax book launch]]>
           </title>
           <publishedAt>2006-06-15T23:25:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-06-15-ajax-book-launch</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>It's <a href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-64060425">right there in the spec</a>, plain as day, but it still makes no frigging sense. I can understand the camelCaps when using DOM methods to set CSS properties  with hyphens in them -- like 'borderRight' (for 'border-right') or 'backgroundImage' (for 'background-image'), but why 'cellPadding' and 'cellSpacing'?</p>

<p>The HTML attributes are 'cellpadding' and 'cellspacing' -- all lowercase, no hyphens. How the hell do these supposedly bright people in the W3C decide these things? Flip a coin? Rock paper scissors? Or do they just default to the <em>least</em> intuitive option?</p>]]>
           </body>
           <title>
               <![CDATA[Table cellpadding and cellspacing with DOM methods]]>
           </title>
           <publishedAt>2006-06-15T22:59:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-06-15-table-cellpadding-and-cellspacing-with-dom-methods</permalink>
</article>
       <article>           <body>
               <![CDATA[<p><strong>Note: Originally this post had a horrible dangling participle. Thanks to a reader's comment, it's still a real head-scratcher -- but thankfully, gramatically correct. I still can't get past the fact that he noticed a grammar problem in a sentence that contains the words "naked" and "Darth Vader mask." Those are some serious editing chops.</strong></p>

<p>While my wife and I were putting our boys to bed tonight after their baths, one of the twins was running around his room naked, wearing a Darth Vader mask. Ah, the joys of fatherhood.</p>]]>
           </body>
           <title>
               <![CDATA[A sentence you don't type every day]]>
           </title>
           <publishedAt>2006-06-02T00:07:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-06-02-a-sentence-you-dont-type-every-day</permalink>
</article>
       <article>           <body>
               <![CDATA[<p><strong>Update: The code in this post is licensed under the terms of the <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License, version 2</a>.</strong></p>

<p>Working on the new fluid layout code for Scooby, I had a seemingly intractable problem -- I needed to do percent-based side-to-side alignment of elements inside two <code>div</code></pre> elements, one positioned directly above the other. The catch was that the lower <code>div</code></pre> scrolled, and the upper one did not.</p>

<p>I tried two or three different things, but couldn't get around it -- ultimately I needed to set a horizontal offset on the top <code>div</code></pre> that would be the same precise width as the scrollbar in the <code>div</code></pre> below.</p>

<p>Interestingly, the irritatating IE bug of <a href="http://www.google.com/search?hl=en&lr=&q=ie6+div+width+100%25+scrollbar&btnG=Search">calculating the 100% width before adding scrollbars</a> to a scrolling div makes this unnecessary -- all you have to do is set the same arbitrary offset for both <code>div</code></pre> elements (as long as it's wider than any Windows scrollbar might be so you don't end up with content under the scroller).</p>

<p>For the well-behaved browsers, though, I just decided to do some hacking, and came up with something that reliably gives you the actual pixel width of the scroller. There is likely a better way to do it, but here's what I ended up with:</p>

<pre><code>function getScrollerWidth() {
    var scr = null;
    var inn = null;
    var wNoScroll = 0;
    var wScroll = 0;

    // Outer scrolling div
    scr = document.createElement('div');
    scr.style.position = 'absolute';
    scr.style.top = '-1000px';
    scr.style.left = '-1000px';
    scr.style.width = '100px';
    scr.style.height = '50px';
    // Start with no scrollbar
    scr.style.overflow = 'hidden';

    // Inner content div
    inn = document.createElement('div');
    inn.style.width = '100%';
    inn.style.height = '200px';

    // Put the inner div in the scrolling div
    scr.appendChild(inn);
    // Append the scrolling div to the doc
    document.body.appendChild(scr);

    // Width of the inner div sans scrollbar
    wNoScroll = inn.offsetWidth;
    // Add the scrollbar
    scr.style.overflow = 'auto';
    // Width of the inner div width scrollbar
    wScroll = inn.offsetWidth;

    // Remove the scrolling div from the doc
    document.body.removeChild(
        document.body.lastChild);

    // Pixel width of the scroller
    return (wNoScroll - wScroll);
}
</code></pre></pre>

<p>Okay, so it's fairly obvious and a bit brute-force.</p>

<p>All it does is add a couple of <code>div</code></pre> elements to the document and actually measure widths with and without the scroller. But I was pretty excited to be able to grab that value correctly and reliably for Safari, as well as for Firefox on Linux and on Windows -- with both the XP "Hasbro" look and the old-skool Soviet-bloc style.</p>

<p>And of course, as you might guess, it's different everywhere. Yes, it is.</p>
]]>
           </body>
           <title>
               <![CDATA[Getting the scrollbar width in pixels]]>
           </title>
           <publishedAt>2006-05-30T22:42:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-05-30-getting-the-scrollbar-width-in-pixels</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Just read a nice article over on <a href="http://www.thinkvitamin.com/">Vitamin</a> about <a href="http://www.thinkvitamin.com/features/webapps/serving-javascript-fast">Serving JavaScript fast</a>, written by Cal Henderson from Flickr.</p>

<p>He touches on a pretty broad range of techniques -- caching, reducing the number connections for downloading, loading your JS libraries asynchronously, or compressing them.</p>

<p>The compression techniques he mentions include both simple gzipping and pre-procesing the file with something like the <a href="http://dojotoolkit.org/docs/compressor_system.html">Dojo Compressor</a> that strips whitespace and comments, and shortens the names of privately scoped variables.</p>

<p>There's also some interesting stuff about caching  where he explains how to use aggressive caching with PHP and then use Apache's mod_rewrite to redirect requests for JS and CSS files to the proper version of a file -- instead of using the standard hack of adding a query string on the end to make the browser grab a fresh copy.</p>
]]>
           </body>
           <title>
               <![CDATA[Vitamin article on serving JavaScript fast]]>
           </title>
           <publishedAt>2006-05-24T00:25:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-05-24-vitamin-article-on-serving-javascript-fast</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I'm in the process of converting all the positioning of UI elements in Scooby from absolute pixel positions to percents, to allow on-the-fly horizontal resizing of the entire UI.</p>

<p>I've got it far enough along now that I can see what it's all going to look like, but it's still a bit like Frankenstein's monster -- stitched loosely together in an ugly way. I can almost see bolts coming out of its neck.</p>

<p>So far the biggest challenge looks like its going to be dealing with the space for the scrollbar on the main scrollable area for normal events that have a set time.</p>

<p>I also haven't ascertained whether or not two block elements overlap if they look like: elementA -- left:0%, width:25%, elementB -- left:25%, width:25%. Basically, does the next element overlap the first if it's left position in percent is the same percent as the width as the element directly to its left? Is that go on 'three,' or 'one, two, three,' and <em>then</em> go?</p>

<p>Is it even possible this will obviate the need for removing that one or two pixels for the CSS border? Could it be so? Pretty please?</p>]]>
           </body>
           <title>
               <![CDATA[CSS position and width in percents]]>
           </title>
           <publishedAt>2006-05-18T11:18:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-05-18-css-position-and-width-in-percents</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>This past week I was at the <a href="http://theajaxexperience.com/">Ajax Experience Conference</a> in San Francisco. Here's my general take on the Ajaxey festivities.</p>

<p>General points of interest:</p><ol>

<li>The number of people. The organizers said they were anticipating around 250 people. I think the real number they said was something like 475 in attendance.</li>

<li>Bleeding-edge Ajax technologies:
a. HTTP streaming (AKA 'comet', server-side push)
b. Local storage for Web apps (currently done in Dojo using JavaScript talking to Flash).</li>

<li>People are still writing their own low-level code. A poll by simple raising of hands indicated that a majority of people (60-70%?) are writing their own toolkits instead of using something like Prototype, MochiKit, Dojo, etc.</li>

<li>A trend by vendors to open up more of their product. Laszlo is now OpenLaszlo, Zimbra is Apache licensing instead of using their own license. Adobe is relaxing pricing for the Flex server, and releasing a stripped-down freebie server version.</li>

<li>Accessibility for Ajax seems to be a big concern and question mark for everybody.</li>

<li>Ideas for JavaScript 2, as presented by Brendan Eich, may bring some significant changes to client-side Web development. His presentation is online here (use right and left arrow keys to navigate):

<a href="http://ajaxian.com/downloads/presentations/eich-ajax-experience-2006/">http://ajaxian.com/downloads/presentations/eich-ajax-experience-2006/</a></li>
</ol>

<p>Sessions I attended:</p>

<p><strong>Introduction to Dojo / Dojo in Depth</strong> (Alex Russell)</p>

<p>A good introduction to a lot of the stuff that makes Dojo cool -- the package system, event.connect, widgets, and io.bind.</p>

<p>The takeaway: Dojo has a pragmatic and extremely well-designed foundation, and it's evolving fast into something that will allow complex Ajax/JS fontends to grow and scale in a fairly painless way. It is still somewhat of a moving target in some areas, so it's probably a good approach to start with pieces that are not very much in flux.</p>

<p><strong>Ajax Beyond the "Cool" factor: Design Principles and Patterns</strong> (Michael Mahemoff)</p>

<p>Applying patterns to Ajax. Demonstrated good use of 'progressive enhancement' for adding Ajax to an existing piece of code. Compared various approaches to Ajax development (e.g., Ajax as an enhancement vs. full-on Ajax app development, JSON vs. XML, and so on).</p>

<p>The takeaway: As Ajax development work begins to be better understood, a common set of patterns emerge and can be shared as best practices.</p>

<p><strong>JSON</strong> (Douglas Crockford)</p>

<p>Introduced JSON with a bit of history and description. Compared to XML for data transfer with Ajax apps.</p>

<p>The takeaway: JSON is not XML, and that's a good thing. It's much simpler, but completely sufficient to represent all but the most esoteric of data structures. Its roots in JavaScript object-literal syntax make it a perfect method for passing objects back and forth between a server and an Ajax frontend.</p>

<p><strong>Beyond Cookies: Persistent Storage for AJAX/DHTML Applications Using Dojo.Storage</strong> (Brad Neuberg)</p>

<p>Introduction to Dojo's local storage system, which can currently use Flash (or cookies of course).</p>

<p>The takeaway: This might be a tenable strategy for allowing offline storage of larger amounts of data -- *if* you don't mind tying your users to a proprietary player like Flash. But dojo.storage also stubs out a basic API for accessing local storage, so it will be ready when Firefox and other browsers actually implement it natively (which might actually be fairly soon).</p>

<p><strong>Building event-driven user interfaces with Dojo</strong> (Dylan Schiemann)</p>

<p>Demostrated a lot of examples from the Renkoo Web app (www.renkoo.com) for managing a complex event-driven Ajax UI. Also described use of HTTP streaming (AKA 'comet') to implement server-side push.</p>

<p>The takeaway: Managing the flow of user/app events in a complicated asynchronous UI is hard, but Dojo's event.connect (publish/subscribe model) can make things a lot more manageable. Even with that, creating a really sophisticated, attractive, and responsive UI still seems to require some degree of hackery. Lastly, server-side push is finally turning into something usable in a real-world Web app.</p>]]>
           </body>
           <title>
               <![CDATA[The Ajax Experience conference]]>
           </title>
           <publishedAt>2006-05-18T01:54:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-05-18-the-ajax-experience-conference</permalink>
</article>
       <article>           <body>
               <![CDATA[<p><strong>Update:</strong> Something has recently happened in the Scooby codebase that broke this fix. The only related change I can think of is that the actual form tags moved from a JavaScript-generated <code>innerHTML</code></pre> call, to being embedded directly in the initial JSP page for the Scooby UI.</p>

<p>So rather than playing more pattycake with this silly issue, I just pulled out a can of <code>innerHTML</code></pre> whoop-ass, and created a little branch in the code for IE just for radio buttons and checkboxes. It's ugly, but it will work reliably.</p>

<p><strong>Note that the following fix is not recommended, but I'll leave the original post here for posterity's sake ...</strong></p>

<p>In the process of working on some DOM code for Scooby that produces form elements, I ran into some really interesting speed bumps making sure the code works properly in IE6. One of them dealt with dynamically created radio buttons.</p>

<p>IE ("As of Internet Explorer 5 ...") <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/createelement.asp">purportedly</a> is able to use the standard <code>createElement</code></pre> method for all types of <code>input</code></pre> elements. However, with my code IE would create the buttons, but they would not work. Quite the buzzkill. Posts like <a href="http://cf-bill.blogspot.com/2006/03/another-ie-gotcha-dynamiclly-created.html">this one</a> and <a href="http://www.sitepoint.com/forums/showthread.php?t=368715">this one</a> confirmed that something is generally awry with the IE's DOM methods for radio buttons.</p>

<p>Then I then noticed a little extra disclaimer in the IE docco:</p>

<blockquote>Attributes can be included with the <code>sTag</code></pre>  as long as the entire string is valid HTML. You should do this if you wish to include the NAME attribute at run time on objects created with the createElement method.</blockquote>

<p>A <code>name</code></pre> attribute? Of course I want it to have a <code>name</code></pre> attribute, it's a form input. The <code>sTag</code></pre> mentioned is the single param passed to <code>createElement</code></pre> -- which according to the W3C DOM spec is supposed to be "the name of the element type to instantiate" (e.g., <code>createElement('input')</code></pre>). And the IE docs are talking about passing HTML in that param?</p>

<p>So, apparently, the only way to assign a <code>name</code></pre> attribute to an <code>input</code></pre> element with DOM in IE is to pass HTML strings to the <code>createElement</code></pre> method instead of just the element type. Wow, serious points for being weird <em>and</em> hackish!</p>

<p>That explained all the code I saw being offered up as the solution for this problem -- creepy-looking stuff like this:</p>

<pre><code>var radio2 =  document.createElement(
    "&lt;input type='radio' name='foo' checked&gt;");</code></pre></pre>

<p>I was trying to remember why this had never bitten me in the ass before, and I remembered that the last time I did any low-level work with dynamic forms was probably implementing the Curriculum-creation tool for the <a href="http://www.knowledgewire.com">KnowledgeWire</a> app.</p>

<p>That was back in the day when I did tons of stuff with <code>innerHTML</code></pre> -- but Mozilla didn't handle it well for form elements (the opposite of IE, naturally). If you rewrote parts of a form with <code>innerHTML</code></pre> in Mozilla it would do weird stuff like add things to the <code>elements</code></pre> collection, but not remove them.</p>

<p>So I had this whole library of functions for doing dynamic form elements with -- you got it -- <code>innerHTML</code></pre> for IE, and DOM for Mozilla. Kind of makes me a little misty-eyed, thinking of the good ol' days of doing everything twice. It worked perfectly for us (it's probably still in use there), and I never touched the innards of it after that.</p>

<p>And now of course now, trying to do the opposite -- make IE's flaky DOM methods for form inputs work -- I was scratching my head trying to come up with something that didn't involve branching code and using <code>innerHTML</code></pre>, or even fouler, passing HTML markup into <code>createElement</code></pre>.</p>

<p>Well, mercifully, as it turns out, in IE6 (which is what we support in Scooby)  inputs created with DOM methods automatically get a <code>name</code></pre> attribute that matches the <code>id</code></pre>. This is reasonable for things like text inputs, but vaguely retarded for radio buttons in that the <code>id</code></pre> for each DOM element is supposed to be unique, and a cluster of radio buttons should all have the same <code>name</code></pre> to make them behave as a unit. But you can at least hold your nose and make that work -- by giving all the form elements in the group -- <em>sigh</em> -- the same <code>id</code></pre>.</p>

<p>What's worse, doing something like creating a whole separate code branch to work around the nasty, false, tricksy DOM methods in IE? Or giving a cluster of radio buttons a common <code>id</code></pre> when the <code>id</code></pre> should be unique? At this point, it's kind of a wash -- both options are equally crappy. I picked the one that didn't require forking the code.</p>

<p>IE is like the sterotypical drunk relative at Christmas time -- he's horrible and irritating, he's not going anywhere, and you can't ignore him.</p>
]]>
           </body>
           <title>
               <![CDATA[IE6 radio buttons with DOM]]>
           </title>
           <publishedAt>2006-04-29T22:09:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-04-29-dom-fun-with-ie6-and-form-elements</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>We've finally got code to deal with event collision in Scooby for both areas of the event canvas -- the timed events in the scrolling area in the middle, and now the all-day events at the top. Kudos again to my co-worker Alec Flett, who did the <a href="http://en.wikipedia.org/wiki/Sparse_matrix">sparse matrix</a> code for the all-day event tiling in Chandler that I used as the basis for the code in Scooby.</p>

<p>And after reading the post on the new blog of Steve Yegge (yes, of <a href="http://opal.cabochon.com/~stevey/blog-rants/">Stevey's Drunken Blog Rants</a> fame) about <a href="http://steve-yegge.blogspot.com/2006/03/math-for-programmers.html">Math for Programmers</a>, I can totally agree with him that "knowing even a little of the right kinds of math can enable you do write some pretty interesting programs that would otherwise be too hard." Once I saw how the tiling stuff worked in Chandler, and got to study a bit about sparse arrays and matrices, it was pretty easy to translate those concepts into the working code in Scooby.</p>

<p>Once I've worked my way through the pile of programming books (<a href="http://www.amazon.com/gp/product/0201633612/">Design Patterns</a>, <a href="http://www.amazon.com/gp/product/0735619670">Code Complete</a>, blah blah blah ...), maybe I'll start doing some 'wax on, wax off' with the math.</p>]]>
           </body>
           <title>
               <![CDATA[Tiling and a sparse matrix]]>
           </title>
           <publishedAt>2006-04-18T00:33:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-04-18-tiling-and-a-sparse-matrix</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Interesting look at <a href="http://www.oreillynet.com/onlamp/blog/2006/04/digg_phps_scalability_and_perf.html">PHP scalability in comparison to Java</a> -- specifically its use at two 'Web 2.0' companies, <a href="http://www.gojobby.com/">Jobby</a> and <a href="http://www.digg.com">Digg</a>.</p>

<p>Does a decent basic breakdown of the different costs -- and the conclusion seems to be that the biggest scalability issues came from the database component. Server tuning for PHP, unsurprisngly, turned out to be very key -- although I was surprised a big part of the solution involved using FastCGI.</p>]]>
           </body>
           <title>
               <![CDATA[PHP scalability at Jobby and Digg]]>
           </title>
           <publishedAt>2006-04-12T22:45:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-04-12-php-scalability-at-jobby-and-digg</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Over the weekend I went on a bit of a coding binge and implemented event block overlap in Scooby's 'timed' events (events that have a start and end time -- not 'all day').</p>

<p>It's a clone of the implementation in Chandler -- some really elegant algorithms for both the block indentation and width calculations written in Python by Alec Flett, one of my co-workers at OSAF.</p>

<p>My task actually ended up being pretty easy. All I had to do was translate what he did into JavaScript, and make it work in Scooby's GUI framework.</p>

<p>I don't know Python (although I have read O'Reilly's <em>Learning Python</em> book), so I had anticipated this would take a week or longer to work out completely. It's proof of Python's simplicity and readability that I was able to knock out a basic implementation over the weekend.</p>

<p>That leaves recurrence and tiling of all-day events to finish up before Scooby will be close to anything that people can actually use -- but getting this overlap stuff working is a pretty big step.</p>]]>
           </body>
           <title>
               <![CDATA[Event overlap in Scooby]]>
           </title>
           <publishedAt>2006-04-10T21:47:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-04-10-event-overlap-in-scooby</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Wow. Merlyn's <a href="http://www.merlyn.demon.co.uk/datelinx.htm">Date and Time Index and Links</a> are an exhaustive bunch of references on dates and times, and using them in programming.</p>

<p>The cool kids may already know about this one, but I hadn't seen it before.  His reference on <a href="http://www.merlyn.demon.co.uk/js-dates.htm">JavaScript and dates</a> alone is a real treasure trove of helpful information.</p>]]>
           </body>
           <title>
               <![CDATA[Merlyn's date and time resources]]>
           </title>
           <publishedAt>2006-04-09T23:59:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-04-09-merlyns-date-and-time-resources</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Wow, can't believe it's been a month and a half since I posted last. It's pretty much been the final big push to get the chapter content for the <a href="http://www.amazon.com/gp/product/0975841947/">book 
</a> all wrapped up.</p>

<p>Last week provided Bug Entertainment for the Whole Family again as we switched to daylight savings time. I had it in the back of my head that there might be some weird bugs surface in Scooby, and I was right -- and just like the <a href="http://www.fleegix.org/articles/2005/11/03/missing-dateadd-datediff">last time</a>, it was something very weird and specific. This time, you couldn't edit all-day events to start on Sunday, April 1st. They'd all jump right over to sit on Monday.</p>

<p>I'll even cop to the fact that it took me a good ten minutes or so to snap to the fact that it was a DST-switchover bug.</p>

<p>The bug was in the <code>Date.diff</code></pre> method in <code>date.js.</code></pre>, comparing by single days. It was doing <code>parseInt</code></pre> of the result -- so in the case of that Sunday, the result of 23/24 was 0.9583333 ... and it would get truncated to zero. The obvious solution (once you know that little gopher hole is there) is to round the result -- an annoying bit of math to have to do every time for a case that happens once a year.</p>

<p>I keep thinking there ought to be a less annoying way to fix that.</p>]]>
           </body>
           <title>
               <![CDATA[Yet another DST-switchover gotcha]]>
           </title>
           <publishedAt>2006-04-08T22:21:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-04-08-yet-another-dst-switchover-gotcha</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Yesterday I was trying a bit of interop now that Scooby is communicating fully with Cosmo using CalDAV.</p>

<p>I used Novell's Evolution as my e-mail client (because it can easily look at mail on NFS shares), but have never used the calendar. But yesterday we had a guy in our <code>#scooby</code></pre> IRC channel trying it out with Scooby, so I thought I'd see if I could make it work as well.</p>

<p>I fired the calendar up, created some events, and then looked for an Export option -- no dice there of course. Not sure if that's just oversight, or if it's because Evo is a commercial app. In any case, to their credit, they do store the data in a standard way (ICS), in an expected location (<code>.evolution/calendar/local/calendar.ics</code></pre>), so it was really easy to import it into Chandler.</p>

<p>I then shared that calender to my local install of Cosmo, and accessed it using Scooby. I was able to edit events with no issues. Kind of interesting to see that Evo seems to have no sense of 'floating,' timezoneless events.</p>

<p>Once I resynced Chandler with that shared calendar on Cosmo, it was easy to export it as an ICS file that I could import back into Evo. The changes I made  in Scooby were there, and everything looked fine.</p>

<p>Serious kudos to the Evo guys for using a standard format for their calender, and even bigger kudos to the guys on the Chandler team for making import/export of calendar data so smooth and seamless.</p>]]>
           </body>
           <title>
               <![CDATA[Round trip from Evo to Scooby]]>
           </title>
           <publishedAt>2006-02-24T11:38:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-02-24-round-trip-from-evo-to-scooby</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>One of the reasons I've not posted in quite awhile is because I've been trying to catch up a bit on the writing schedule for my book, while also prepping the client-side pieces of the Scooby codebase for our upcoming <a href="http://wiki.osafoundation.org/bin/view/Projects/FirstScoobyRelease">Scooby 0.1 Release</a>.</p>

<p>So I'm crunching away on the book this evening, and checking out the O'Reilly site to see if they have any kind of search API so I can add them into the Web services code in the book. I do an idle search on 'ajax' to see what their search location URI looks like, and the very first hit in the results is the entry for <a href="http://www.oreilly.com/catalog/0975841947/index.html">my book in their catalog</a>. Kind of weird and unexpected to see that.</p>

<p>I guess in this case it would be silly of me to complain about the sheer unhelpfulness of having an unpublished book show up first in the results. Looks like the default sort for the results is by date.</p>
]]>
           </body>
           <title>
               <![CDATA[A nice little surprise]]>
           </title>
           <publishedAt>2006-02-24T00:42:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-02-24-a-nice-little-surprise</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>A post over at Why's Ruby blog on <a href="http://redhanded.hobix.com/inspect/showingPerfectTime.html">using Ruby to pitch Unix timestamps out to JavaScript</a> led me to this really nice, long post by Johan Sundstrom on <a href="http://ecmanaut.blogspot.com/2006/01/ajax-date-time-time-zones-best.html">best practices for dealing with JavaScript and timezones</a>. (Why had a really elegant take on strftime, by the way.)</p>

<p>Both of these posts talk about the three options for dealing with timezone issues in your Web app:</p>

<ul>
<li>Doing the full-on user-preference-based timezone thing
<li>Totally punting and not dealing with the issue
<li>A solution somewhere in the middle -- using UTC timestamps for everything, and letting the client decide what timezone to show.</li>
</ul>

<p>They advocate the third solution, which likely provides the most reasonable timezone coverage for most Web apps without ridiculous amounts of work.</p>

<p>Unfortunately for us, Scooby will have to have a much more robust timezone implementation, so we're eventually going to have to implement a complete user-preference-based system. Our conversion to the new <a href="http://lists.osafoundation.org/pipermail/scooby/2006-February/000135.html">ScoobyDate</a> data type for event dates is a good start in that direction.</p>

]]>
           </body>
           <title>
               <![CDATA[JavaScript timezone tastiness]]>
           </title>
           <publishedAt>2006-02-12T22:34:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-02-12-javascript-timezone-tastiness</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Just got through reading a post by Joel Spolsky declaring that there are <a href="http://joelonsoftware.com/items/2006/02/08.html">Too Many AJAX Calendars</a>. Reading it didn't exactly give me a warm and fuzzy feeling given that my day-to-day job is working on, well, an AJAX calendar.</p>

<p>His frustration stems from the fact that he tried six or so different AJAX calendars -- most of them beta or 1.0 releases -- and none of them seem to do a lot of the stuff he expects a calendar to do.</p>

<p>This is what he calls the Marimba Phenomenon, after a dot-com-era company that launched a minimally functional product that was a huge disappointment due to high expectations from a humongous onslaught of PR hype:</p>

<blockquote>When you get premature publicity, lots of people check out your thing, and it's not done yet, so now most of the people that tried your thing think it's lame, and now you have two problems: your thing is lame and everybody knows it.</blockquote>

<p>This has proved to be a bit of a problem for Chandler in the past, and it's something we're trying to exercise caution with for Scooby as well.</p>

<p>Joel thinks that this bumper crop of AJAXey Web calendars has been caused by the swirl of ongoing rumor about a Google online calendar. His idea is that these folks are building online calendars in the hopes that Yahoo will ultimately buy them a la <a href="http://www.oddpost.com/">Oddpost</a>. This is not an entirely unreasonable idea (or an unreasonable business strategy, as my co-worker Bobby points out), and I suspect that the guys at <a href="http://www.kiko.com">Kiko</a> or <a href="http://www.planzo.com/">Planzo</a> would love to be snapped up by Yahoo for a few skillion dollars.</p>

<p>Whatever the reason, given the profusion of these beta-quality AJAX calendars, we need to make sure that the project Web site and documentation for the upcoming Scooby 0.1 release underline the things that set Scooby apart from these other offerings:</p>

<ul>
<li>All the Scooby code is freely downloadable and available under the Apache License, Version 2.0.</li>
<li>Scooby is to be standards-compliant, and should eventually be able to serve as a generic CalDAV client.</li>
</ul>

<p>It probably also wouldn't hurt to emphasize that this is a developer's pre-release, not something people should expect to use to get work done. At least I probably don't have to worry about Joel trying to use it. He seems to be done with AJAX calendars for awhile.</p>

]]>
           </body>
           <title>
               <![CDATA[Joel on AJAX Calendars]]>
           </title>
           <publishedAt>2006-02-09T22:30:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-02-09-joel-on-ajax-calendars</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Last week I downloaded the IE7 Beta 2 Preview Release.</p>

<p>It's not horrid, although the IE team really drank the MS Office 12 no-standard-toolbar Kool-Aid, so what you have instead of named dropdown menus evenly spaced across the top of the window is dropdown menus coming out unlabeled icons in random places all over the UI.</p>

<p>Asa Dotzler has a nice <a href="http://weblogs.mozillazine.org/asa/archives/2006/02/my_thoughts_on.html">side-by-side comparison of IE7 versus Firefox</a> that gives a good, detailed breakdown of this IE7 Preview.</p>

<p>To install it, by the way, you still have to reboot. Of course.</p>]]>
           </body>
           <title>
               <![CDATA[IE7 Breakdown]]>
           </title>
           <publishedAt>2006-02-06T11:36:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-02-06-ie7-breakdown</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Just heard an acronym today that I thought was pretty cool. I'm sure I'm late joining in with the cool kids, but today was the first time I heard XMLHttpRequest referred to as 'XHR.'</p>

<p>This is fantastic, since I've been tripping over this horribly named term for a couple of years now.</p>

<p>Sure, it's an acronym of acronyms, but who cares? It's so much easier to say. For me now, it's simply 'XHR.' No more wondering why XML is all caps, and HTTP is not. No more falling on my face trying to spit it out during an impassioned tech discussion.</p>

<p>Best of all, it still has that letter 'X' in it.</p>]]>
           </body>
           <title>
               <![CDATA[XHR ... still has that letter 'X']]>
           </title>
           <publishedAt>2006-02-03T22:03:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-02-03-xhr-still-has-that-letter-x</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>AJAX allows you to move a lot of the 'smarts' in your Web app from the backend out to the client. This raises some interesting questions -- e.g., how much of your app's logic should you offload to the browser? Brad Neuberg has an interesting Weblog post on this question of <a href="http://codinginparadise.org/weblog/2006/01/ajaxdhtml-tutorial-should-i-render-my.html">thick versus thin clients with AJAX</a>.</p>

<p>With a thick client, the client-side code has all three of the model, view, and controller, and the server is simply a source of data, providing some kind of simple API for retrieving it -- like REST, XML-RPC, or JSON-RPC. It returns structured data like DSV, XML, or JSON which the client uses for generating UI markup on the fly.  This is the approach we're going with for Scooby.</p>

<p>In a thin-client setup, the browser provides only the controller, and user actions trigger requests to the server, which actually generates all the markup. The client then just pulls it down and inserts in the UI (usually using a method like <code>innerHTML</code></pre>). This is much less AJAXey, and pretty close to the way Web pages and Web applications have been working for a long time the only difference here is that the requests can be asynchronous, and the entire page doesn't have to be re-rendered at once.</p>

<p>The upside to thick-client approach is that it takes full advantage what is possible with AJAX-style development, and creates a really responsive, performant application.</p>

<p>Brad really nails it with his description of the potential downside of this approach:</p>

<blockquote>The Thick Client approach moves most of the software engineering to the client; it's weaknesses are that it is a new environment for server-side programmers, many of whom don't respect JavaScript or the level of software engineering it can require to produce quality results. It is difficult to find DHTML programmers who know how to work within this environment.</blockquote>

<p>The thin-client approach is much more comfortable for server-side programmers and traditional apps programmers. As Brad puts it, "It's [sic] strength is that it builds on familiar and available server-side skills, and can sometimes be used to leverage an existing system."</p>

<p>The main problem with doing everthing on the server of course is that each user action requires a round trip back and forth, and as your application gets more complicated, it begins to bog down. This approach doesn't scale well, and only works with the simplest UIs.</p>

<p>My suspicion is that with the influx of server-side devs and traditional apps programmers doing Web stuff, specifically AJAX-style development, that a lot of supposedly AJAXey applications are leaning heavily on the thin-client approach, which doesn't maximize the advantage of using AJAX in the first place. It often results in a really pokey-feeling application.</p>

<p>Having a lot of experience on the client-side, I of course am biased heavily toward offloading as much stuff to the browser as possible. I think that usually provides the optimal end-user experience, as you do as much as possible in real-time right there where the user is. But there are issues with rendering your markup client-side that are not mentioned in Brad's post, and I think are worth noting. I'll write about those in another post.</p>

]]>
           </body>
           <title>
               <![CDATA[Thick or thin clients for AJAX]]>
           </title>
           <publishedAt>2006-02-02T21:39:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-02-02-thick-or-thin-clients-for-ajax</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>One of the reasons the posts have been so sparse here is that I've been working on a book. The kind folks over at <a href="http://www.sitepoint.com">SitePoint</a> have tapped me to write a book for them on building AJAX Web applications.</p>

<p>I'm far enough along with it now that I can say I think it's going to be pretty damned decent, and I'm really looking forward to getting it out there so I can share lessons learned in my years working on the <a href="http://www.knowledgewire.com">KnowledgeWire </a>app, and now on <a href="http://wiki.osafoundation.org/bin/view/Projects/ScoobyHome">Scooby</a>.</p>

<p>SitePoint are the publishers of the excellent book <a href="http://www.sitepoint.com/books/dhtml1/">DHTML Utopia</a>, by <a href="http://www.kryogenix.org/">Stuart Langridge</a> (inventor and champion of the term "unobtrusive DHTML") -- and have a distribution deal with <a href="http://www.oreilly.com/">O'Reilly</a>, including their <a href="http://safari.oreilly.com/">Safari Bookshelf</a> online reference library.</p>

<p>So it would appear there's a least a fair chance more than three people will actually read my book, which is kind of cool.</p>

<p>The best thing so far about the book deal has been that SitePoint has agreed to release all the source code for the book under an open-source license. It's all going to be available for download under the <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License, Version 2.0</a>, the same license we use for Scooby.</p>

<p>That fits nicely with my position at OSAF -- but more importantly, I think it's just a fundamentally smart thing for SitePoint to do. It builds good karma with the community, and can only help book sales.</p>
]]>
           </body>
           <title>
               <![CDATA[AJAX book for SitePoint]]>
           </title>
           <publishedAt>2006-01-29T23:20:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-01-29-ajax-book-for-sitepoint</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Spent some time last night upgrading my work laptop from <a href="http://www.ubuntulinux.org">Ubuntu Linux</a> version 5.04 (Hoary Hedgehog) to 5.10 (Breezy Badger). Now I should be able to run Chandler on my work machine instead of having to move over to my little Windows lappy every time I need to look at it.</p>

<p>I just changed my <code>/etc/apt/sources.list</code></pre> to point to the Breezy repositories, and then used <code>apt-get update</code></pre> and <code>apt-get dist-upgrade</code></pre> to do the deed.</p>

<p>I'm continually impressed by Ubuntu in general. Considering the magnitude of the changes, there was surprisingly little headache.</p>

<p>I did have some issues with blocking packages (which might have stemmed from having OpenOffice 1 and 2 both installed). Here's the error message I was getting:

<blockquote><pre><code>dpkg: error processing
/cdrom//pool/main/o/openoffice.org2-helpcontent
/openoffice.org2-help-en-us_1.9.129-0.1ubuntu5_all.deb
(--unpack):
trying to overwrite
`/usr/lib/openoffice2/help/en/scalc.idx/DOCS.TAB',
which is also in package openoffice.org2-calc</code></pre></pre></blockquote>

<p>It seems that the Ubuntu base package depended on a language pack that depended on the OpenOffice.org Help content which it couldn't install because it was already there. Typical dependency-chain annoyance. However, as you might expect with open source software, a quick Google search led me to <a href="http://ubuntuforums.org/showthread.php?t=76896">post on the Ubuntu forums</a> which solved the issue for me -- I just had to resort to <code>dpkg -r</code></pre> on each of the individual OpenOffice.org apps (<code>dpkg -r openoffice.org2-calc openffice.org2-draw openoffice.org2-impress openoffice.org2-math openoffice.org2-writer</code></pre>). Other than this minor irritation, the upgrade was smooth as butter.</p>

<p>One thing I do miss from my Gentoo days was the freedom from those kind of dependencies -- although I of course do not miss the endless compiling. And even with having to remove OpenOffice components manually during this upgrade, it's not nearly as annoying as a lot of the RPM-tail-chasing I can remember from using Redhat.</p>

<p>While I was at it, I bit the bullet and set up the newest (development) version of <a href="http://www.enlightenment.org">Enlightenment</a> -- version 0.17, referred to as <a href="http://www.get-e.org/">E17</a>.</p> 

<p>I've been using Enlightenment for years now, and this is a completely new version -- things look totally different.</p>

<p>It's a development version, so it's a bit incomplete and crashy, but it is serious eye candy, with some gorgeous drop shadows and transition effects. And it's surprisingly efficient as well. Even with all the new chrome, it feels way less ponderous than the default GNOME desktop.</p>

]]>
           </body>
           <title>
               <![CDATA[Upgrading to Breezy and E17]]>
           </title>
           <publishedAt>2006-01-27T18:20:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-01-27-upgrading-to-breezy-and-e17</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I guess it's been a fairly eventful day -- I got to shake hands with former US Vice President Al Gore, and also to meet and speak briefly with author and tech-law expert Larry Lessig.</p>

<p>Vice President Gore was in the OSAF office to give a presentation on global warming, which was both brilliant and extremely frightening.</p>

<p>After the presentation, as I was getting coffee, I got into a conversation with a guy who was also waiting around for a refill. As we were talking, I began to realize he looked a bit familiar, so I asked who he was -- of course it was Larry Lessig, who serves as CEO of <a href="http://creativecommons.org/">Creative Commons</a>, which shares office space with OSAF.</p>

<p>It's kind of funny -- I was a bit disappointed to have missed the virtual talk he gave in-world in <a href="http://www.secondlife.com">Second Life</a>, but ended up being able to ask him about it in person today. He seemed pretty amused by the entire thing, especially by the virtual 'signing' he did of his book.</p>
]]>
           </body>
           <title>
               <![CDATA[An eventful day]]>
           </title>
           <publishedAt>2006-01-19T21:53:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-01-19-an-eventful-day</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Finally needed some JavaScript code to handle heavy date-manipulation lifting, with all the week-to-week navigation and date-difference calculation happening in Scooby.</p> 

<p>I got my start with Web dev working with MS Active Server Pages in VBScript, and whatever else you may say about the general crappiness of that environment, VB does have some seriously nice date handling fu. I got very used to being able to call on <code>DateDiff</code></pre> and <code>DateAdd</code></pre>, and be reasonably sure my results would not be borked.</p>

<p>Of course in JavaScript, you have to do everything yourself -- so I implemented a fairly accurate rendition of those two functions in JavaScript: <code>Date.diff</code></pre> and <code>Date.add</code></pre>. The code is all in the <code>date.js</code></pre> library we use in Scooby -- along with the <code>Date.strftime</code></pre> function which has all the normal datetime/string formatting goodness you'd expect from <code>strftime</code></pre>. The code is available under the Apache License, Version 2.0, and you can download <a href="http://svn.osafoundation.org/server/scooby/trunk/src/webapp/js/scooby/util/date.js">the latest version</a> from OSAF's SVN server.</p>

<p>There are still a few holes here and there -- notably manipulation by 'quarter' interval. But it sure is nice to stop having VB envy with my JS code.</p>
]]>
           </body>
           <title>
               <![CDATA[JavaScript <code>DateAdd</code> and <code>DateDiff</code>]]>
           </title>
           <publishedAt>2006-01-10T17:24:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-01-10-javascript-code-dateadd-code-and-code-datediff-code</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Now that the AJAX hype is really going full-bore, we were bound to see folks posting their particular spin on the evolution of AJAX. I've seen two of these recently, both of which get things pretty much completely wrong.</p>

<p>One of them seems to be inaccurate by dint of narrowness of experience. Aaron Schwartz posts his <a href="http://www.aaronsw.com/weblog/ajaxhistory">A Brief History of Ajax</a>, which does actually contain many good factual elements. But any post that purports to be about the history of AJAX that contains the phrase "Shortly before web development died out" is of course immediately suspect.</p>

<p>Maybe he's being hyperbolic; I don't know. But I was doing Web development starting in the late 90s right up to today, and even after the crash it seemed that companies were still moving everything slowly to the Web, and that Web-based business with sound business plans were still thriving.</p>

<p>His original 'history' doesn't even mention obvious primitive versions of AJAX-style dev like the hidden <code>iframe</code></pre> trick, remote scripting with the JavaScript tag <code>src</code></pre>, or even the ugly hack of nested framesets that lots of people were using back before XMLHttpRequest and DHTML.</p>

<p>He does add some correction at the bottom that mentions the <code>iframe</code></pre> trick, but states incorrectly that it "never took off." This is completely incorrect in that it was a really ubiquitous hack that everyone was using in their Web apps to post stuff back to the server without reloading a page.</p>

<p>The other AJAX 'history' post I've seen recently is one from Garrett Smith that's out of whack due to its partisan worldview. Get a load of the title: <a href="http://garrettsmith.net/blog/archives/2006/01/microsoft_inven_1.html">Microsoft invented Ajax: Let's give credit where it's due</a>. Makes you want to read it just because you'll know it's worth a chuckle.</p>

<p>He starts his post off by decrying Mitchell Baker's comment about how Microsoft's browser monopoly caused Web development to stagnate. Her comment, that Web 2.0 would have happened sooner without the Microsoft monopoly is not something any serious Web developer would debate. Certainly not after enduring close to five years of a slowly rotting development platform -- IE 6, that made absolutely no forward progess, saw no new development, got no new functionality after the Netscape bugaboo was safely dead.</p>

<p>In fact, no sane person -- not even the most rabid Microsoft patriot -- could argue, not with a straight face anyhow, that we would even have a new version of IE coming out if it weren't for the competition they are now facing from Firefox.</p>

<p>But the heart of the post is the bit that leaves me unable to decide whether I should laugh or cry:</p>

<blockquote>Microsoft invented Ajax in 1999. It just took the rest of the software world 6 years to catch up.</blockquote>

<p>To achieve this Zen-like simplicity of belief in the power of Redmond, he narrowly defines AJAX as (1) the ability to modify HTML on the client side and (2) XMLHttpRequest -- both of which states, made their debut on Internet Explorer.</p>

<p>In fact, DHTML, or the ability to modify the UI in the browser without reloading the page, was something that came out at roughly the same time in both browsers -- IE 4 and Netscape Navigator 4, in 1997. And if you want to go further back than that, it was possible to do primitive AJAX-style changes to the UI with image rollovers and framesets back in Netscape Navigator 3, released in 1996. IE 3, back then, was ... well, let's just say it's a very painful memory.</p>

<p>Sure Microsoft introduced XMLHttpRequest, and there was much rejoicing. It's a big step forward that makes the lives of all Web devs much easier. That doesn't mean they invented AJAX any more than Netscape did by creating JavaScript.</p>

<p>As I keep pointing out -- AJAX is not something new. Neither Microsoft, nor anyone else 'invented it.' The collection of technologies and techniques we call AJAX is just another step in the evolution of something we've been doing since there were browsers to develop Web pages and applications for.</p>
]]>
           </body>
           <title>
               <![CDATA[Revisionist AJAX History]]>
           </title>
           <publishedAt>2006-01-10T11:27:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-01-10-revisionist-ajax-history</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Roger Johansson has an excellent post over on his blog on <a href="http://www.456bereastreet.com/archive/200410/bring_on_the_tables/">how to make tables more usable in the modern world of CSS</a>. The point is not to avoid them all together, but make sure to address the issues they cause with accessibility, usability, and with your ability to repurpose content.</p>

<p>The post purposefully sidesteps the question of whether or not you should throw out tables completely for layout purposes, as the CSS advocates argue you ought to. This works well, and allows him to focus on the right question: "It's about using tables for their original purpose: marking up tabular data."</p>]]>
           </body>
           <title>
               <![CDATA[Feeling the table love]]>
           </title>
           <publishedAt>2006-01-09T10:22:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2006-01-09-feeling-the-table-love</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Found a really great post today off Reddit on the <a href="http://builder.com.com/5100-6404-1045782.html">Ten Commandments of Egoless Programming</a>. This is great stuff.</p>

<p>The closest I ever came to this kind of an environment was in my startup days working at KnowledgeWire, before the merger with <a href="http://www.eduneering.com">Eduneering</a>. And I have to say the guys I worked with there managed to keep things that way for a long time even after that. Of course things inevitably change as a company grows, and bureaucracy and politics insinuate themselves more and more into the fabric of your workday in the name of 'imposing structure.'</p>

<p>So it's good to be back in something very close to an egoless environment working at OSAF. Maybe because it's a smaller organization, maybe because it's a non-profit -- but folks really do seem to check egos at the door here.</p>

<p>Another nice one was the <a href="http://www.technicat.com/writing/programming.html">Seven Habits of Highly Effective Programmers</a>. Some of the stuff in here -- like building early, merging often, and keeping your code clean and commented -- is stuff you should already know. But it's still good to see it codified in a simple list, and to be reminded of how important these things are.</p>

<p>There are also a few -- for example "Code with Style," "Manage Thyself," and "Continuous Education," which gave me a little bit more opportunity for thought. Kind of nice to know too that after all, "There is Such a Thing as a Stupid Question."</p>]]>
           </body>
           <title>
               <![CDATA[Inspirational Friday]]>
           </title>
           <publishedAt>2005-12-23T13:18:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-12-23-egoless-programming</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>It appears that Web 2.0 boredom has finally well and truly set in.</p>

<p>We've passed the point of the <a href="http://blogs.zdnet.com/ip-telephony/?p=805">Web 2.0 backlash ("Web 2.0 is bunk.")</a> from Russell Shaw on his Weblog at ZDNet, and now we're finally hitting our stride with some backlash against the backlash in a <a href="http://webreakstuff.com/blog/2005/12/why-web-20-makes-sense/">defense of Web 2.0</a> from the Frederico Oliveira at WeBreakStuff, and a big ol' <a href="http://www.crunchnotes.com/?p=88">"fuck the begrudgers" shout-out</a> from Mike Arrington over at CrunchNotes.</p>

<p>You always reach a point of buzzword fatigue with stuff like this, and it looks like the current tug-of-war over the term "Web 2.0" is a great example of this. No one in the discussion seems to be dismissing the actual technologies or techniques -- nor the explosion of innovative products and services driven by them.</p>

<p>No, the argument seems to be solely over the use of the term "Web 2.0" to describe them.</p>

<p>Sure it's nice to have such a neat term that ties together all these loosely related concepts like 'openness' and 'interconnectedness' and 'perpetual beta.' And sure, the Web 2.0 moniker gives us Web folks a rallying cry -- it reminds us that the Web itself and its bedrock utility for doing actual business didn't go bust along with the bubble. But most geeks are contrarians at heart, and once the Marketing guys get their hands on something -- even if it's a word with some decent geek cred like "Web 2.0" -- the gut reaction is to start casting about for something sharp to stick in it.</p>


<p>I'm just waiting around for the backlash against the backlash against ...</p>]]>
           </body>
           <title>
               <![CDATA[Let the Web 2.0 backlash ... against the backlash ... begin]]>
           </title>
           <publishedAt>2005-12-22T21:47:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-12-22-let-the-web-2-0-backlash-against-the-backlash-begin</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Cool, looks like we're getting our own conference for this here AJAX stuff.</p> 

<p>Brian, a co-worker of mine, has kindly clued me in to the upcoming <a href="http://ajaxian.com/archives/2005/12/announcing_the.html">AJAX Experience</a> (no relation to the <a href="http://www.jimi-hendrix.com/">Jimi Hendrix Experience</a>), which will be held in San Francisco, May 10-12, 2006, hosted by the <a href="http://www.nofluffjuststuff.com/">No Fluff Just Stuff</a> Java Symposium Series.</p>

<p>The list of speakers looks like a nice who's who of JavaScript experts and toolkit developers, so I think this thing will actually be worth showing up for. I think I'll try to attend -- maybe work it in with a visit to the OSAF office.</p>]]>
           </body>
           <title>
               <![CDATA[AJAX Conference -- "The AJAX Experience"]]>
           </title>
           <publishedAt>2005-12-20T23:02:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-12-20-ajax-conference-the-ajax-experience</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>A recent post on QuirksMode about <a href="http://www.quirksmode.org/blog/archives/2005/11/javascript_and_1.html">JavaScript and "serious" programmers</a> asks the question "Who will create the AJAX apps?"</p>

<p>The post really delves into one of the most fundamental problems that the AJAX boom creates: the push and pull between the old-school client-side devs (like me) who've been doing this JavaScripty stuff for years, and server-side devs, who's bosses are telling them "whip me up some of that AJAX stuff in this next app."</p>

<p>As these AJAXified Web apps continue to push into the traditional app space, there will be more plain old apps programmers or server-side devs forced to deal with the client-side stuff, and more client-side devs expected to do more of the heavy lifting in client-side code.</p>

<p>I think one of the best things about this post is that after highlighting this issue, Peter-Paul immediately heads off at the pass the inevitable response that the problem is a lack of good libraries.</p>

<p>He states flat out that <a href="http://www.digital-web.com/articles/keep_javascript_simple/">he's not a fan of libraries</a>. Good man -- I'm not a fan myself. And he punctutates his dislike with this really insightful question for the "we'll just use libraries" crowd:</p>

<blockquote>Suppose you're my boss and order me to write a Java application for you, despite my abysmal ignorance of all things Java. I buy a technical reference book, ask around for the best libraries in town, and with these aids start to create my application. Would you, being my boss, consider this a healthy situation in which I'm guaranteed to deliver a quality product to our clients?</blockquote>

<p>This issue isn't use of libraries. The issue is people who want the benefit of new tech without learning how to use it. The post continues by pointing out the obvious: "I feel that libraries are sometimes regarded as substitutes for knowledge. Without knowing a programming language you can't use it. Libraries are just tools, not magic wands."</p>

<p>Too true. A large number of people coming into the #ajax channel on Freenode with questions are asking things like "My AJAX request won't work. I'm using Prototype. Can you help me?" These guys are server-side devs or C++ app developers who are being forced to use AJAX by their CTO or Marketing department or whatever, and want to just plop in a library and have it work.</p>

<p>And in many cases, it works fine. But when something goes south, these guys don't have the foggiest idea where to start troubleshooting. Usually, it's something like "Use a <code>window.onload</code></pre> event listener to make sure your div has loaded before writing to it."</p>

<p>Libraries are of course a good use of abstraction, and sometimes are an indispensable tool for getting your work done. When the abstraction breaks down, however, it does really help to know what's going on inside. Joel Spolsky's <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">Law of Leaky Abstractions</a> has some good stuff to say about the ups and downs of using a black box to do stuff.</p>
]]>
           </body>
           <title>
               <![CDATA[AJAX devs: client- or server-side?]]>
           </title>
           <publishedAt>2005-12-15T10:51:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-12-15-ajax-devs-client-or-server-side</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Alex Bosworth has a good post over on his Weblog on <a href="http://www.sourcelabs.com/blogs/ajb/2005/12/10_places_you_must_use_ajax.html">10 Places You Must Use Ajax</a>. This is a nice, thoughtful list, and it's apparent Alex has a good visceral grasp of not just AJAX, but of interactive Web site or Web application design -- it's a great idea to highlight the areas where the unique qualities of AJAX techniques serve a Web page or Web app in best stead.</p>

<p>While the title might be a bit strongly worded ("must" sounds pretty obligatory), in some ways this is much more helpful than the initial inclination you might have to give a list of what's wrong in AJAX development. (Although he has actually also compiled a nice list of exactly that, <a href="http://alexbosworth.backpackit.com/pub/67688">Ajax Mistakes</a>.)</p>

<p>It's great to know what pitfalls to avoid, but AJAX development seems to be attracting large numbers of delevopers from a traditional applications development background. A lot of these guys don't have the intuitive understanding of what AJAX means for Web development that an old-school Web dev might have. Telling these guys where best to apply the new AJAX fu might give them a real leg up on exploiting the strength of the Web medium.</p>

<p>This is particularly important given the common misperception that AJAX means making your browser-based app act like a desktop app. Your AJAX Web app may be way more responsive and interactive than a traditional Web app, but there are still really important differences between the two.</p>

<p>Traditional applications developers doing AJAX Web app development with JavaScript AJAX toolkits -- especially those who don't have real experience with Web apps -- may end up ignoring the realities of creating a remote application that runs in a Web browser, and creating horrible, pokey-feeling faux-desktop-apps that make the end users want to cry.</p>

<p>Alex's post is good place for these guys to start -- before they roll up their sleeves and get their hands dirty with XMLHttpRequest, or some toolkit that wraps that stuff up for them.</p>

]]>
           </body>
           <title>
               <![CDATA[Obligatory AJAX]]>
           </title>
           <publishedAt>2005-12-13T11:40:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-12-13-obligatory-ajax</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Just saw a pretty nice post on Dion Hinchcliffe's Weblog of the <a href="http://web2.wsj2.com/the_best_web_20_software_of_2005.htm">Best Web 2.0 Software of 2005</a>.</p>

<p>It's got a pretty nice rundown of Web apps in a lot of different categories including Social Bookmarking, Online To-Do Lists, Blog Filters, Online Calendars, and even Web-Based Word Processing.</p>

<p>Of course it includes a lot of the usual suspects including Zimbra, Writely, Kiko, Digg, Reddit, Delicious, Memeorandum, and so on.</p>]]>
           </body>
           <title>
               <![CDATA[Web 2.0 software survey]]>
           </title>
           <publishedAt>2005-12-12T22:30:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-12-12-web-2-0-software-survey</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>AJAX is officially an entrenched technolgy buzzword. We've finally got Jacob Nielson intoning on his Weblog, <a href="http://www.usabilityviews.com/ajaxsucks.html">"AJAX Sucks Most of the Time"</a>. At least he did put that qualifier in there.</p>

<p>I'm always inclined to take what Nielson says with a grain of salt, but I have to say I think he's right on target in this post. And he even shows a remarkable ability to adjust a previous position:</p>

<blockquote><p>For new or inexperienced Web designers, I stand by my original recommendation. <strong>Ajax: Just Say No.</strong></p>

<p>With respect to the use of ajax by highly skilled Web designers, I have changed my opinion somewhat: people who really know what they are doing can sometimes use ajax to good effect, though even experienced designers are advised to use ajax as sparingly as possible.</p></blockquote>

<p>Of course given that fact that my primary occupation at the moment is creating a Web application <em>entirely in AJAX,</em> I can't really get behind that "sparingly as possible" bit.</p>

<p>And Nielson seems still to be stuck on what he describes as issues with "the current implementation of ajax pages" -- a really "Web 1.0" way of thinking about the Web, as a collection of pages. The so-called Web 2.0 thinking of course is of the Web as a collection of <em>applications.</em></p>

<p>Nonetheless, some of the points he raises are valid -- issues with mobile-device users, printing, and search engines. He also of course raises the standard-issue problem of the "AJAX Back button problem."</p>

<p>In some contexts of course, there is no Back button, and no "back" to go to. You find this in the newer kinds of Web applications that are working together to create the next iteration of the Web. And "skimping on the pate" of AJAX technologies isn't going to get that job done</p>

]]>
           </body>
           <title>
               <![CDATA[Applying AJAX]]>
           </title>
           <publishedAt>2005-12-07T11:30:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-12-07-applying-ajax</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I saw a pretty decent post off of Slashdot on <a href="http://dkrukovsky.blogspot.com/2005/07/how-to-write-comments.html">commenting your code</a>, from <a href="http://dkrukovsky.blogspot.com">Make the Software Shine</a>.</p>

<p>This was interesting timing since yesterday as I was working on Scooby, I was noticing how many pieces of code were sadly lacking comments.</p>

<p>Of course it was the knee-jerk guilt reaction -- it's pretty well drilled into me that a good programmer comments his code. But then I was also thinking about how quickly the code is evolving, and that I've actually had to remove large swaths of comments along with code I was refactoring.</p>

<p>I thought the Weblog post raised an interesting point about when it's really appropriate to comment your code:</p>

<blockquote>The point to start writing comments is... when the code is ready to be presented for others. This could be the time before commit to a main source repository, or insert your case here. For this time, I have pretty stable class design, and good chance my comments will live long.</blockquote>

<p>I'm going to keep up with the inline comments in the code, but I believe I'll leave the more detailed JSDoc-style commenting until stuff starts to stablize a bit.</p>]]>
           </body>
           <title>
               <![CDATA[When to comment code]]>
           </title>
           <publishedAt>2005-11-30T11:40:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-11-30-when-to-comment-code</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Just saw a link off Digg to an entry on the on the Microformats wiki about something called <a href="http://microformats.org/wiki/rest/ahah">AHAH</a> (Get it? "Aha!"). The article headline describes it as "AJAX 2.0," and breathlessly explains that is "backed by David Hansson, the creator of Ruby on Rails." The wiki entry for it introduces the concept thusly:</p>

<blockquote>AHAH is a very simple technique for dynamically updating web pages using JavaScript. It involves using XMLHTTPRequest to retrieve (X)HTML fragments which are then inserted directly into the web page, whence they can be styled using CSS.</blockquote>

<p>This fairly silly stuff, even from the perspective of your normal level of silly AJAX/Web-dev hype. Maybe it's getting the double dose by way of its association with Rails.</p>

<p>Let's deconstruct this -- first of all, leaving out the 'J' in the acronym: does this mean it somehow doesn't use JavaScript? And adding the 'H' for 'HTTP' -- AJAX also uses HTTP, remember the XMLHttpRequest object? And as for the 'H' for 'HTML' -- despite what <a href="http://www.hixie.ch/advocacy/xhtml">certain ideologues might think</a>, most right-thinking people are using XHTML these days anyway, so the cool AJAX letter 'X' we love so much covers that markup coming back from the server.</p>

<p>Why is it necessary to come up with a new acronym to describe something that is clearly just another flavor of JavaScript-driven DHTML with XMLHttpRequest? (Also known as 'AJAX.' Yes, with an 'X' at the end. It's this cool new Web-dev technique. You see, back in the old days of Web development ...)</p>

<p>Never mind the "AJAX 2.0" thing. That just raises all kinds of weird questions -- If AJAX is Web 2.0, and this 'AHAH' stuff is AJAX 2.0, does that mean that AHAH is then Web 4.0? This makes my head hurt.</p>
]]>
           </body>
           <title>
               <![CDATA[This one goes to 2.0]]>
           </title>
           <publishedAt>2005-11-26T14:01:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-11-26-this-one-goes-to-2-0</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Today I had the unique opportunity to do a little work on OSAF's main application, <a href="http://wiki.osafoundation.org/bin/view/Projects/ChandlerHome">Chandler</a>, which is rapidly approaching its 0.6 release.</p>

<p>The little pop-up box that displays when you select the "About Chandler" option in the help menu, as it turns out, is rendered from an HTML file, so I was asked to to a little tweaking to make it look a bit nicer.</p>

<p>The joy in this is that the HTML rendering capabilities we're talking about are for HTML 3.2 -- circa Netscape Navigator or IE version 3.</p>

<p>Felt kind of nostolgic, reaching down into the ol' toolbox and blowing the dust off the hoary old "single-pixel transparent GIF" trick to get stuff to space right. Almost brought a tear to my eye.</p>

<p>Actually, what really made me want to cry was all the hideoous embedded <code>font</code></pre> tags. The horror.</p>

<p>It was nice to take that trip down memory lane, but I'd never want to go back there to live. As broken as the current CSS spacing and alignment model is, it beats the hell out of that.</p>

]]>
           </body>
           <title>
               <![CDATA[Bringing a tear to my eye]]>
           </title>
           <publishedAt>2005-11-22T22:49:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-11-22-bringing-a-tear-to-my-eye</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I just got another e-mail about that old article I wrote for O'Reilly Network about using AJAX to do song search for my Webcast radio station.</p>

<p>Interestingly though, this e-mail wasn't asking about the AJAX stuff -- this guy wanted to know about the server-side Ruby code I mention in the article.</p>

<p>Ruby is fantstic for Web programming -- simple or complicated. Unfortunately everyone is so focused on the Rails hype that plain vanilla Web programming kind of takes a back seat.</p>

<p>For using Ruby's DBI to talk to a database -- including how to iterate through a recordset, you can check out the <a href="http://www.kitebird.com/articles/ruby-dbi.html">excellent resource at Kitebird</a>. And LinuxJournal has a good article that talks about <a href="http://www.linuxjournal.com/article/8356">how to use the basic Ruby CGI module for Web programming</a>.</p>

<p>Most of the CGI examples use that complicated HTML-generation stuff to craft the markup for the page. I actually tend just to build a string of content throughout the script execution and then write the whole thing out at the end -- it's way less complicated for someone like me who's comfortable working directly with markup, and managing string data myself.</p>

<p>I do it kind of like this:</p>


<pre><code>#!/usr/bin/ruby

require 'cgi'
require 'dbi'

cgi = CGI.new
content = ''

content += 'Some stuff&lt;br/&gt;'
content += 'Some more stuff'
content += &lt;&lt;DOC
This is content inside of a heredoc.&lt;br/&gt;
I can do linebreaks and stuff in here.
DOC

cgi.out() { content }</code></pre></pre>

<p>You can get the <a href="http://www.rubycentral.com/book/lib_network.html">full rundown on the CGI module</a> from the online version of the Pickaxe book as well.</p>

<p>You can get a performant Ruby CGI app by using either <a href="http://www.fastcgi.com/">FastCGI</a> or <a href="http://www.modruby.net/">mod_ruby</a>. The kind folks at ZTtracks have a somewhat old but nice resource on <a href="http://www.zytrax.com/tech/lang/ruby/index.html">setting up Apache to serve a mod_ruby Web app.</a></p>]]>
           </body>
           <title>
               <![CDATA[Ruby CGI with DBI]]>
           </title>
           <publishedAt>2005-11-21T21:25:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-11-21-ruby-cgi-with-dbi</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>The guy over at <a href="http://edevil.wordpress.com/">EDevil's Weblog</a> has done a really nice <a href="http://edevil.wordpress.com/2005/11/14/javascript-libraries-roundup/">comprehensive roundup of AJAX/JavaScript libraries</a>.</p>

<p>OSAF has a <a href="http://wiki.osafoundation.org/bin/view/Projects/AjaxLibraries">similar page</a> that we originally used to narrow the list for what we wanted to use in Scooby, and it appears people are adding to it, but EDevil's list is much more extensive.</p>]]>
           </body>
           <title>
               <![CDATA[AJAX/JavaScript libraries roundup]]>
           </title>
           <publishedAt>2005-11-15T13:12:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-11-15-libraries-roundup</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I got an e-mail last week from a developer who is trying to do something kind of interesting with AJAX and a networked application:</p>

<blockquote><p>I have a WebSphere application running on my local machine. I can't do some of the data validation myself so I have to connect to another server (it is on the same domain but sitting on the different box) to get that information. Basically, I am trying to grab some content out of that html page using AJAX and use that information to render my own page (like screen scraping). Does the AJAX approach work in this case?</p>

<p>I can't seem to make this to work because my application and the other application are running on different boxes.</p></blockquote>

<p>Interesting, because networked Web applications speaking REST/SOAP over HTTP are ideal for tying together disparate pieces of infrastructure, as Peter Yared (ActiveGrid) explains very eloquently in his <a href="http://peteryared.blogspot.com/2003/09/application-servers-2004-big-muffin-in.html">"Big Muffin in a Donut World"</a> post (as well as his more forward-looking thoughts on <a href="http://peteryared.blogspot.com/2003/09/next-language.html">the future direction of programming languages</a>). These posts are fairly old, but still do a pretty good job of explaining the benefit of HTTP and scripting languages as infrastructural glue.</p>

<p>At first blush then, AJAX would seem to be just another step in that same direction, with AJAX HTTP requests allowing the browser to tie together data from various assets on the network.</p>

<p>However, you still have all your commonesense paranoia to consider when giving this kind of power to a client app -- naturally the ability to make arbitrary HTTP requests in a programmatic way with JavaScript has a lot of potential for misuse. So the browser sensibly disallows making requests with XMLHttpRequest to a different domain (actually any different machine name, even on the same subdomain) from the one from which the current page was served.</p>

<p>Of course security considerations are all relative, and what might be a perfectly sensible level of paranoia in an open networking environment might be irritating overkill for developers trying to cobble together a useful solution somewhere where they control the entire network.</p>

<p>A simple solution to this cross-domain request problem  is to use a server-side proxy script on the originating server to relay AJAX requests to other servers.</p>

<p>I replied to the e-mail with a very quick example of a PHP proxy script which uses the <a href="http://pear.php.net/">PEAR</a> module <a href="http://pear.php.net/package/HTTP_Request">HTTP_Request</a>:</p>

<pre><code>&lt;?php
require_once "HTTP/Request.php";

$url = $_REQUEST['url'];
$req =& new HTTP_Request($url);

if (!PEAR::isError($req-&gt;sendRequest())) {
    print $req-&gt;getResponseBody();
}
?&gt;</code></pre></pre>

<p>The URL to be requested -- along with its query string -- is passed along as a (URL-encoded) variable called "url." The script simply relays the AJAX request, and prints out whatever it gets back from the other server.</p>

<p>It's quite a simple little script, and only handles basic <code>GET</code></pre> requests. But it would be pretty easy to add whatever other stuff you need -- <code>POST</code></pre> support, authentication tokens, other goodies -- to allow it to handle all the different sorts of requests you need.</p>

<p>It's admittedly irritating to have to push work back onto the server, but the server's not doing much here. And since the requests still happen asynchronously, and originate on the client, the user experience is still very much an AJAXey one.</p>

]]>
           </body>
           <title>
               <![CDATA[Cross-domain AJAX requests]]>
           </title>
           <publishedAt>2005-11-07T18:56:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-11-07-cross-domain-ajax-requests</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Well, looks like everybody's finally on board the AJAX hype train, and it's pulling out of the station. There was an <a href="http://online.wsj.com/public/article/SB113098635587487074-3diFzslPm_iutdYLU2C5e4DinUA_20061103.html/new">article yesterday</a> in the Wall Street Journal Online about what it describes as a "hot new, Web-based technology called Ajax" which is attracting lots of investement money.</p>

<p>Amazingly, they do note that the technology isn't completely new, although they follow this up with the predictable, grossly inaccurate statement that "Ajax-type technologies were first developed by Microsoft in the late 1990s as part of its Internet Explorer Web browser."</p>

<p>Yes, the XMLHttpRequest object originated in Explorer, but Web devs were doing stuff with framesets to create AJAXey Web apps back in the Netscape 4 days. Of course back then, as I always note, we called it 'DHTML.' And, I should add, we did it barefoot, uphill both directions, and we were thankful for it.</p>

<p>The article focuses mainly on companies being built around AJAX technologies, with a list including some of the usual suspects like <a href="http://www.kiko.com">Kiko</a>, <a href="http://www.zimbra.com">Zimbra</a>, and <a href="http://www.writely.com">Writely</a>, and <a href="http://www.meebo.com/">Meebo</a>. It also mentions a company I've not heard of before called <a href="http://joyent.com/">Joyent</a>, who are apparently also doing an e-mail/calendaring/groupware type of thing.</p>

<p>I had a look at their site -- it's a commercial product, with enterprise pricing and QuickTime demos. Unfortunately they don't provide a live demo, so it's impossible to tell anything about the actual quality of the product.</p>

<p>The article quotes Zimbra's CEO Satish Dhamaraj as saying that there's a "venture capital frenzy" over AJAX. Guess that just shows you should never underestimate the power of a good acronym, especially one with the letter 'X' in it.</p>

<p>The article also notes, "Other technology veterans are rolling their eyes over the Ajax frenzy." Yeah, I'm actually kind of grateful now for the Ruby on Rails hype because it gives me the occasional break from the AJAX hype.</p>]]>
           </body>
           <title>
               <![CDATA[AJAX, AJAX, everywhere]]>
           </title>
           <publishedAt>2005-11-04T23:38:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-11-04-ajax-ajax-everywhere</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Today one of my co-workers shared a post he found by Alex King on a <a href="http://www.alexking.org/blog/2005/11/02/nasty-php-oddity/">Nasty PHP Oddity</a> dealing with dates. The issue was caused by doing date incrementation using the simple expedient of adding or subtracting 86400 seconds to a Unix-style timestamp to move forward or back a day.</p>

<p>This works rather nicely for the most part, except for the day when Daylight Savings Time starts or ends, when a day is an hour longer or shorter.</p>

<p>Now I'll 'fess up here -- I actually got bitten in the ass by the exact same issue (only in JavaScript, not PHP) working on Scooby's week-to-week navigation code last week. Kind of felt like a doofus, actually -- a familiar feeling.</p>

<p>The predictable response on the OSAF dev mailing list was that the Chandler devs should all be using the Python 'timedelta' to increment or decrement dates. A good idea -- if your language gives you a nice, built-in, error-free way to avoid calculating a bunch of perilous date-related stuff manually, then using it is pretty obviously a Good Thing.</p>

<p>The problem here is that neither PHP nor JavaScript have native methods like Python 'timedelta' or (from my bad old days programming in ASP) DateDiff or DateAdd in VBScript for smoothing out the weird complexities of dealing with dates.</p>

<p>After a bit of Googling, I did find something for JavaScript called <a href="http://slingfive.com/pages/code/jsDate/jsDate.html">jsDate</a> which looks fairly promising, and seems to be very well maintained. The only issue I can see with it is that the author doesn't clearly state what license the code is available under -- he just says "Use freely, but be honest about it.  I just ask for credit."</p>

<p>I've gone ahead and implemented a <a href="http://wiki.osafoundation.org/bin/view/Projects/JavaScriptStrftime">JavaScript <code>strftime</code></pre></a>. Sure would be nice to have a <code>dateAdd</code></pre> too.</p>
]]>
           </body>
           <title>
               <![CDATA[Missing dateAdd, dateDiff]]>
           </title>
           <publishedAt>2005-11-03T21:16:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-11-03-missing-dateadd-datediff</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>We have to do a lot of date formatting in the Scooby UI, and after about the fifth time of writing a one-off function to format a date in a certain way, I realized what I really needed was a JavaScript implementation of the normal <code>strftime</code></pre> function you find in the major scripting languages like Perl, PHP, and Ruby -- it's a truly indispensible tool for anyone who has to twist and manipulate dates into different formats for display.</p>

<p>Not wanting to reinvent the wheel of course, I looked around and found what looks like a <a href="http://www.openparty.net/2004/0425/javascript-strftime/">nice implementation</a> by <a href="http://www.openparty.net">Jonathan Buhacoff</a>. Unfortunately, it's GPL-licensed, and all the Scooby code is released under the more permissive Apache License v. 2, so we can't use it.</p>

<p>So I've implemented a <a href="http://wiki.osafoundation.org/bin/view/Projects/JavaScriptStrftime">Javascript <code>strftime</code></pre></a> for us to use with the Scooby project, and like all other Scooby code, it's Apache-licensed. You can download the <a href="http://svn.osafoundation.org/server/scooby/trunk/src/webapp/js/date.js">latest stable version of the date.js file</a> from OSAF's SVN server. I've also created some <a href="http://wiki.osafoundation.org/bin/view/Projects/JavaScriptStrftime">basic documentation</a> on the OSAF Wiki.</p>

<p>I hope this thing can be useful for other folks besides just us. Please send me patches for fixes and improvements.</p>
]]>
           </body>
           <title>
               <![CDATA[JavaScript <code>strftime</code>]]>
           </title>
           <publishedAt>2005-10-26T19:38:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-10-26-javascript-code-strftime-code</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Yesterday I spent most of the day working from a Photoshop file from Mimi, hammering together the new "Chandler Landing Page" for the upcoming 0.6 release of the Chandler PIM client. It's in SVN, so if you're so inclined you can see the <a href="http://svn.osafoundation.org/sandbox/mde/demo/chandler_landing/index.html">current iteration of the page</a>.</p>

<p>Mimi likes using her Mac-specific fonts for the layout, so I tried to avoid putting any text into graphics, since it can look kind of weird seeing multiple sans-serif fonts competing on the same screen (i.e., Lucida Grande in the graphics and Verdana for all the actual content text). So all the text you see is actual text, which allows each platform to pick one font and run with it.</p>

<p>I also used this as an excuse to put Lucida Grande on my Ubuntu dev machine, so I can see things the way all the Mac-using devs at OSAF do. It was surprisingly painless, once I was able to remember which utils to use to generate the fonts.scale and fonts.dir files (<code>mkfontscale</code></pre> and <code>mkfontdir</code></pre> respectively) after adding the TTF fonts.</p>

<p>As for the layout, it was interesting working on something with that level of detail, that combined graphics and text, especially since I originally approached it with the idealistic notion of trying use pure CSS layout -- none of those tricksey, false tables to get stuff to sit where it needs to on the page.</p>

<p>This rapidly descended into pure comedy, because, as I mentioned, it's a somewhat complex layout that involved stuff like, oh, say ... <em>aligning</em> things. Yes, CSS is still pretty much borked for stuff like vertical alignment, and doing floats with elements of variable widths.</p>

<p>I only mention that because those are things that worked nicely with table-based layout circa ... I guess, maybe Netscape Navigator 3?</p>

<p>So, until they get that stuff right (and be "right," I mean "actually displaying as advertised in the major browsers"), you can pry my XHTML 1.0 Transitional DTD and my tables from my cold, dead fingers.</p>]]>
           </body>
           <title>
               <![CDATA[Layin' it out old skool]]>
           </title>
           <publishedAt>2005-10-21T21:59:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-10-21-layin-it-out-old-skool</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Ever have one of those days where you spend hours and hours on a single bug ... and make zero progress? Yeah, that was me today.</p>

<p>Firefox (both Linux and Windows, so far) exhibits an irritating bug with some very particular conditions, which is making me tear my hair out.</p>

<p>It only seems to happen with elements created with DOM-manipulation methods, and affect the <code>div</code></pre> they are sitting in -- one with with <code>overflow:auto</code></pre> that allows scrolling. The bug is this: if you set the opacity of one of the sub-<code>div</code></pre>s at the same time you're setting other style properties like <code>top</code></pre> or <code>left</code></pre>, the first time you move that <code>div</code></pre>, it will cause the scroll thumb for the scrollbar on the main <code>div</code></pre> to stop recongnizing mouse input. Clicking on the scroll thumb has no effect.</p>

<p>If you move the <code>div</code></pre> again, everything's fine. If you change the opacity before you move the <code>div</code></pre> around, everything's fine.</p>


]]>
           </body>
           <title>
               <![CDATA[Firefox opacity irritation]]>
           </title>
           <publishedAt>2005-10-19T20:36:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-10-19-firefox-opacity-irritation</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Spent most of the day today wrestling with implementation details for Scooby. It was an interesting day in that my co-worker Bobby learned some stuff about JavaScript, and I learned some stuff about good appliation design.</p>

<p>The first issue we sort of ran aground on was the weird 'multithreadedness' of JavaScript execution. My first experience with this was the occaision of my learning the work 'deterministic.'</p>

<p>I had some code where some stuff that happened in a sub-function was clearly finishing long after statements in the main code that were much futher down on the page. A co-worker of mine, a database guy told me that that was not possible -- that programming languages have to be 'deterministic.' When I sat him down and showed it to him, he grumbled and pronounced it a bug in the JavaScript implementation.</p>

<p>Bug or not, it seems that the JavaScript interpreter hands off execution of the sub-function to another thread, and blythely continues executing the main sequence of code with the assumption that everything works hunky-dory in the sub-function, and seemingly with no concern for the timing of it.</p>

<p>I don't know if this is some kind of optimization to speed execution, or what, but it sure can bite you in the ass, since it is totally 'non-deterministic,' and seems not to be what most programmers expect. It only takes a moment to come up with the simple workaround of writing your code in the main thread to wait for a return value from the sub-function, of course, but that does feel kind of ad-hoc and crappy.</p>

<p>If anybody has any clue as to why this happens, I'd love to hear more -- the rationale for that design decision, or whatever technical details I'm capable of understanding.</p>

<p>The other irritation was caused by the way I designed some of the classes for the Scooby app -- I'd allowed some of the controller code to creep into my model (the main calender event data class), and the end result was that it completely borked the calls to the new ScoobyService methods Bobby wrote for saving calendar events.</p>

<p>The root of the issue turned out to be a reference to a DOM node in the data class. Ah, yes -- good ol' DOM-node references wreaking havok again. I'm still trying to figure out exactly what was going on there, but the end result was that JSON-RPC was trying to serialize something that looked like the entire DOM tree for the Scooby calendar app. When you examined the JSON object in the log, you could see huge swaths of table markup, and even form elements showing up in there.</p>

<p>The only thing we could figure was that DOM nodes have references to their parents, or to the main document. That's the only explanation for how all that stuff ended up in our object, because the object property was literally a single <code>div</code></pre> element.</p>

<p>Obviously the solution is to keep the data partitioned off from the rest of the app. Interesting to see that sometimes there actually are practical benefits to a more rigorous adherence to the MVC paradigm, instead of just that warm feeling inside that your code is 'properly' done.</p>
]]>
           </body>
           <title>
               <![CDATA[Multithreadedness and DOM-node madness]]>
           </title>
           <publishedAt>2005-10-18T18:53:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-10-18-multithreadedness-and-dom-node-madness</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>There's a nice article over at <a href="http://particletree.com/">ParticleTree </a> on the <a href="http://particletree.com/features/the-hows-and-whys-of-degradable-ajax/">Hows and Whys of Degradeable AJAX</a>. The first suggestion they have for doing a really degradeable interface is to do your development with JavaScript turned off.</p>

<p>Now, in today's day and age, I tend to think that folks surfing around without JavaScript should expect their Web experience to be pretty broken. But there may be specialized instances where the target user-population for the app would require this kind of approach.</p>

<p>The <a href="http://wiki.osafoundation.org/bin/view/Projects/CosmoHome">Cosmo</a> app at OSAF is a good example of this. The target group for this app is stated to include (and I quote) "pointey-headed Unix admins," and a large fraction of these dudes, clearly, will have JavaScript turned off.<p>

<p>Another good example is mobile platforms. After playing around with a Pocket PC running <a href="http://www.microsoft.com/windowsmobile/default.mspx">Windows Mobile</a>, it's clear that JavaScript is only <em>mostly</em> working in the mobile version of Internet Explorer. The most glaring omission, that broke the app I was trying to use, was lack of support for the <code>onclick</code></pre> event listener on normal page elements.</p>

<p>Unless there are compelling reasons, I'm not a huge fan of maintaining multiple competing versions of the same code. Even if you develop a programmatic way to generate both versions from the same base, you still have some amount of tweaking to do, and of course real testing on both platforms.</p>

<p>However, if you know people are going to be using your app with less-than-fully-capable devices, there are a lot of easy things you can do to prepare your app. You can start by -- ugh -- turning off JavaScript.</p>


]]>
           </body>
           <title>
               <![CDATA[Degradeable AJAX]]>
           </title>
           <publishedAt>2005-10-06T13:35:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-10-06-degradeable-ajax</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Finally got around to trying to set up Japanese-language support on my Ubuntu laptop (running 5.04, "Hoary Hedgehog"), which is the machine I've been using day-to-day since starting work at OSAF.</p>

<p>With each new Linux distro I've used, the process for setting up Japanese has always been a completely different and totally excruciating process. And once it was set up, it using the Japanese language in a specific app required setting up a bunch of screwy environment variables in a terminal like this:</p>

<pre><code>LANG=ja_JP.ujis
LC_ALL=ja_JP.ujis
LINGUAS="ja_JP.ujis"
LESSCHARSET=japanese
export LANG LC_ALL LINGUAS LESSCHARSET</code></pre></pre>

<p>The other alternative was using an entirely Japanese-language environment, which is pretty unappealing for a someone like me who speaks it as second language.</p>

<p>So imagine my shock, surprise, and delight when simply following the instructions in <a href="http://www.mrbass.org/linux/ubuntu/scim/">this page on Ubuntu CJK</a> provided me with seamless Japanese support that just frigging works.</p>

<p>This is huge. Using Japanese on this machine now is as easy and trouble-free as it is on my wife's Mac. I cannot say enough in praise of the good people at Ubuntu and the <a href="http://www.scim-im.org/">SCIM Project</a> who have obviously done piles of work to make using multiple languages under *nix this easy. I can actually copy-paste Japanese text between apps -- something I haven't been able to do since back in my Mac OS 9 days.</p>

<p>This is more exciting than when printing from Ubuntu "just worked" last week in the OSAF office, when Windows couldn't find a single printer on the network. Strange times we're living in, my friends.</p>]]>
           </body>
           <title>
               <![CDATA[Ubuntu de Nihongo ga ...]]>
           </title>
           <publishedAt>2005-10-02T22:35:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-10-02-ubuntu-de-nihongo-ga</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>A day or so ago I read Tim O'Reilly's long article on the question <a href="http://www.oreillynet.com/pub/a/oreilly/tim/news/2005/09/30/what-is-web-20.html">What is Web 2.0</a> -- part of the ongoing discussion of where the Web and technology in general seem to be heading. An interesting part of that seems to be the question of the terminology that frames the discussion, -- i.e., how much of is it actual substance, and how much of it is just buzzwords used as a Jedi Marketing mind-trick to keep the interest of the guys in the suits writing the checks.</p>

<p>My first inclination, jaded human being that I am, is right along the lines of this great cartoon showing <a href="http://www.ok-cancel.com/comic/105.html">Three Different Views on AJAX</a>. (I love the second Marketing drone babbling, "Our apps feature extreme AJAX to the max! Badabing!"). At some level, I feel like the developer who doesn't want to utter the term "AJAX," because of the obvious absurdity -- this thing Web developers have been doing for years has snowballed into a huge phenomenon in a large part due to having a cool acronyn with the letter "X" in it.</p>

<p>On the other hand, there seems to be some value in having a nice, neat congnitive hook to hang a complicated group of concepts on. And for the always-messy world of technology, with its high rate of change, buzzterms like "Web 2.0" "tagging," "REST," and "AJAX" seem to serve that purpose pretty well. They're useful on two different levels -- as a way to describe (and sell) this stuff to non-technical people, and as a point of common reference for the techies to talk about how to use it and the affect it's having.</p>

<p>It is interesting, though -- since usage of these terms evolves somewhat organically in the currents of discussion, you have a lot of different interpretations, and conflict over definitions -- like the subtle distinction between "free software" and "open source." (Witness another very recent article on the O'Reilly Network -- <a href="http://www.onlamp.com/pub/a/onlamp/2005/09/29/what-is-free-software.html">What is Free Software</a>.) These are two terms which often refer to the same pieces of software, but have very different agendas.</p>

<p>"AJAX" is another good example cutting the other direction, as a single term that has developed two very distinct meanings. The original definition describes the use of a particular technique for a Web app to communicate with the server. But there is a second meaning which seems to be in increasingly wide usage (along with goofy capitalization as if it's not an acronym -- "Ajax") that refers to a whole range of behaviors (drag-and-drop, transitions) characteristic of a Web app that acts much like a desktop app. This is the usage of the term that you're seeing the aspiring Marketing Obi-Wans pulling out to use in their presentations. And who can blame them? "DHTML" doesn't have the letter "X."</p>]]>
           </body>
           <title>
               <![CDATA[Jedi mind-tricks?]]>
           </title>
           <publishedAt>2005-10-02T13:16:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-10-02-jedi-mind-tricks</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>This week I'm out here at the OSAF office in San Francisco. It's a nice change to be someplace where there are open businesses and the gas stations actuallly have gas.</p>

<p>I rode out Rita in a hotel room in northwest Houston, after evacuating from my home in southeast Houston -- a little trip that took 11 hours during the excruciating mass exodus on Thursday. Yeah, and I didn't even leave the city.</p>

<p>The trip home on Saturday took about an hour (yes, exactly the same route) -- and there was no real damage to my house. Better to be safe than sorry, I guess, but part of me wonders if it even makes sense to listen to my local government officials during crises like this.</p>

<p>Did I mention how happy I am that my wife and kids are back in Japan visiting her folks?</p>

<p>Since I have a convenient natural disaster to blame my braindead state on, I'm just going to punt today and post a couple of links I've been meaning to put up here for awhile. These are AJAXey, "Web 2.0" calendar applications. Since I'm working on Scooby, which at this point is essentially a Web-based calendar client, I tend to pay a lot of attention to similar applications.</p>

<p>One I noticed some weeks back was <a href="http://www.kiko.com">Kiko</a>, which advertises itself as providing "all of the functionality of offline calendar software, and all the convenience of online access." It's pretty impressive for being the work of a couple of guys over a couple of months. The interface is a bit clunky in spots, but it does give you the idea of how a little AJAX-fu can be applied to the problem of organizing calendar events.</p>

<p>The other is <a href="http://www.planzo.com/">Planzo</a>, which bills itself as being "The way web calendar was supposed to be." I got the heads-up on Planzo from Brian Skinner, who is doing some seriously interesting stuff over at <a href="http://www.openrecord.org/">OpenRecord.org</a>. Planzo is also the work of just two guys -- and it's apparently so cool that even <a href="http://gwbush.planzo.com/">US presidents</a> and <a href="http://bclinton.planzo.com/">retired presidents</a> use it.</p>]]>
           </body>
           <title>
               <![CDATA[Escape from Houston]]>
           </title>
           <publishedAt>2005-09-26T20:24:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-26-escape-from-houston</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Yeah, so they did away completely with the standard toolbar in Microsoft Office. Here's <a href="http://channel9.msdn.com/showpost.aspx?postid=114720">fairly lengthy video interview</a> with Julie Larson-Green, the manager of the Office team, describing the new interface. I really need to get my act together here. I saw this last week, and am only just now posting on it.</p>

<p>I guess I'll withold judgement until  I actually use the thing (although if Fate smiles on me that day may never come), but something about this does smell of change for the sake of change. Maybe the OpenOffice.org folks are getting a mite too good at cloning the Office interface -- no way to know exactly what all different factors are driving this stuff.</p>

<p>But even is you suspend your normal suspicion of MS motives, and assume that a large driver of this change is genuinely trying to serve the needs of the customer, I have to admit I'm a bit dubious about such a radical change all at once to a UI system that has been evolving somewhat organically over time. I'm also crusty and set in my ways, so when something demonstrably works, I set the bar a bit higher for making big changes to it.</p>

<p>The one interesting thing I do take away from the video, though is how eerily like an AJAX Web-app the new Office interface has become. The lack of standard menus is a big part of that, but there's also all the live preview effect and drop-down sheets/menus that look like stuff straight out of a DHTML application.</p>

<p>I don't know if they intended this, or if it's just part of of the ongoing convergence between desktop and Web apps. Maybe playing with the current crop of new AJAX apps has helped the Office team step outside of the normal application-design box.</p>

<p>If, however, this is cross-pollination from Web-apps (and I'm only saying it might be), then that's a pretty telling sign of where things are going, given the status of MS Office as a Grandaddy productivity app.</p>]]>
           </body>
           <title>
               <![CDATA[Microsoft Office 12 Video]]>
           </title>
           <publishedAt>2005-09-20T22:25:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-20-microsoft-office-12-video</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I was seeing a lot of sporadic errors running Typo with mod_ruby -- typical of the problems I have seen trying to run multiple, disparate Ruby Web-apps under a single Apache instance with mod_ruby. This is apparently due to the way that the Ruby interpreter embedded in the apache child process persists data between requests.</p>

<p>I had managed to find ways to code around the problem with all my homegrown Web-apps, but Typo doesn't seem to be quite that accommodating. Most of the Rails docs seem to assume using FastCGI instead of mod_ruby, and now I see why.</p>

<p>Shugo Maeda, the creator of mod_ruby, has an entry on his Weblog that talks about <a href="http://blog.shugo.net/articles/2005/08/04/typo-on-mod_ruby">how to use Typo under mod_ruby</a>, but what are trivial fixes to a genius like Maeda-san, don't look so trivial to a techie peon like myself.</p>

<p>In any case, with all the sporadic 500 errors -- I punted, and for the last couple of days I've been running Typo as an old-school CGI. And man, that was seriously sluggish -- like me without my morning coffee: horribly, excruciatingly slow.</p>

<p>So tonight, after wrestling with the config a bit, I managed to get FastCGI set up with surprisingly little pain. I even found a really nice post on Scott Laird's Weblog on <a href="http://scottstuff.net/blog/articles/2005/07/19/apache-tuning-for-rails-and-fastcgi">Apache tuning for Rails and FastCGI</a>, that shows how to switch FastCGI to static mode to improve performance.</p>

<p>FastCGI does indeed seem to be pretty damned fast,and if it proves to be stable, I'll likely look into moving some of my other Ruby Web-app code over. It'll be nice to enjoy the benefits of decent performance and not have to worry so much about shared Ruby processes in the server, stepping all over each other.</p>]]>
           </body>
           <title>
               <![CDATA[Fleegix on FastCGI]]>
           </title>
           <publishedAt>2005-09-13T22:08:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-13-fleegix-on-fastcgi</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Besides all the recent work on the Scooby week-view prototype, I also recently got to work on a fun little one-off project that involved a presentation some of the OSAF folks are going to make to the <a href="http://www.stonesoup.org/">Common Solutions Group</a>.</p>

<p>They wanted a chart-like document that showed the work going on at OSAF, divided into different tracks, and indicating the different phase of development for each track. There was a need to use a lot of expandable (i.e., "Click here to see more ...") text to allow more of the chart to be seen in one eyespan. I learned a new word during the design discussions -- <em><a href="http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGControls/chapter_18_section_7.html">disclosure triangle</a>,</em> which is the little expando-triangle thingie in the Mac OS Finder that you click to see the contents of a folder.</p>

<p>This project turned out to be a great opportunity to play with <a href="http://www.mozilla.org/xmlextras/xmldataislands/">XML data islands</a>. Since it needed to be a template that non-developers could use, I created a data-source section in XML to hold all the content, and then programmatically built the page from that.</p>

The <a href="http://www.fleegix.org/demo/timeline.html">current version of the code</a> is up on the demo server here.]]>
           </body>
           <title>
               <![CDATA[Fun with data islands]]>
           </title>
           <publishedAt>2005-09-13T20:27:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-13-fun-with-data-islands</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>I awoke this morning to find, via an e-mail from a kind co-worker, that I was the recpient of a very public spanking (and not the warm, sexy kind) in <a href="http://bob.pythonmac.org/archives/2005/09/09/mochikit-cons-or-not/">a post on Bob Ippolito's Weblog</a>.</p>

<p>Bob took serious issue with "misinformation" about his <a href="http://www.mochikit.com/">MochiKit</a> JavaScript toolkit in a page I had put up on the OSAF Wiki about <a href="http://wiki.osafoundation.org/bin/view/Projects/AjaxLibraries">different AJAX/JavaScript libraries</a>. The page was part of our process in deciding what toolkit we wanted to use in Scooby, but apparently, people are using it as a reference.</p>

<p>First of all, I'm aghast that anyone is actually looking at that page. I figured that the content on the page was of passing interest to about three of my co-workers, and that's it.</p>

<p>Second, to be completely honest, I do have to cop to one real screw-up in what I wrote -- I had written that MochiKit's AJAX library (called 'Async') does not provide the HTTP status code when a request errors out. In point of fact, it does. Bob writes:</p>

<blockquote><code>XMLHttpRequestError</code></pre> object has a req object that corresponds to the failed request, and for convenience a number property that corresponds to <code>req.status</code></pre>.</blockquote>

<p>However, on taking a very close look at the rest of what I wrote, going over the MochiKit Async.js source again, and reading Bob's post, I have to say that, despite Bob's extremely emphatic protestations to the contrary, I feel like the rest of what I wrote was accurate: The Async API does not provide a POST method, or a built-in way to access the response from the server as an XML document fragment.</p>

<p>I won't bore the three people who ever read this by shoving all the excruciatingly technical details and the somewhat subjective arguments into this blog post, but I'll be happy to go over the whole deal with any interested people by e-mail, or whatever, if any people actually wants to do that to themselves.</p>

<p>So I wrote Bob what I hope was a nice, polite e-mail apologizing for mischaracterizing MochiKit's capabilities, and asking him to have a look at the revised page to make sure he thinks it's accurate.</p>

<p>But you know what would have been really cool?</p>

<p>It would have been really cool if Bob had been kind enough to e-mail me about what he thought I had screwed up, so I could have made corrections to the page, rather than taking me to task about it publicly in his Weblog.</p>

<p>As an addendum: I already got an e-mail response back from Bob. He made the valid point that there are mulitiple versions of the Wiki page, with multiple names, so it's hard to see who he should have sent an e-mail to. On the other hand, his complaints about it being too hard to set up an account on the Wiki to correct the page himself ring a little hollow given that lots of other people are clearly able to figure out how to to it.</p>]]>
           </body>
           <title>
               <![CDATA[A public spanking]]>
           </title>
           <publishedAt>2005-09-10T21:12:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-10-a-public-spanking</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Okay, I've finally decided to stop lying to myself. I know I'll never have the time to implement comments or RSS feeds -- or any of that other stuff you expect with a decent Weblog -- with my own handrolled Webapp.</p>

<p>So, I finally did it. I bit the bullet, and had another go at installing Rails so I could run this Weblog on Typo.</p>

<p>The issue was, of course, Rubygems. I just couldn't get the damned thing installed because it kept complaining about wanting ruby-zlib. Now, I'm sure the knee-jerk reaction from the Rubyist will be to blame Debian/Ubuntu's irritating habit of chopping up the Ruby distribution in to multiple packages. All the posts I could find said just to install the Debian package for ruby-zlib. That of course did me zero good. And since I compile my Ruby from source anyway, a missing package <em>shouldn't</em> have been a problem, right?</p>

<p>Wrong. ruby-zlib apparently is not part of the default Ruby distro. So even if you build it from source, you'll be missing one of the vital components you need to install Rubygems, which you need to install Rails, which you need to install Typo. Whew. A huge word of thanks to <a href="http://mentalized.net/journal/2004/12/01/putting_debian_on_ruby_rails/">this guy</a>, who clued me in to the idea of installing ruby-zlib from source. Once I  got that bad boy in place, installing Rubygems, and installing Rails, and installing Typo were pretty much a snap.</p>

<p>All I can say is that Rails better be pretty damned cool, given what a pain in the ass it's been to install.</p>

<p>So, rather than reinventing the wheel here, I've finally got Typo installed. It looks like a pretty nice Weblog package, and I'm looking forward to putting it through its paces.</p>]]>
           </body>
           <title>
               <![CDATA[Finally, Typo]]>
           </title>
           <publishedAt>2005-09-09T20:36:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-09-finally-typo</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>My new co-worker Bobby (congrats, man!!) just sent me an e-mail asking about my last post. He wanted to know what tools are available to find memory leaks in IE.</p>

<p>Unfortunately, I don't know of any tool to find stuff like that. (I'd love to know if there are any.) That's one of the many irritations with IE, that there're no tools for developing JavaScript. My need for tools is pretty modest, too. The Moz/Firefox JavaScript console is all I really need -- just something to tell me what's fucked up, and where. IE doesn't even have that. And that's kind of piling on, because stuff breaks way more often in IE.</p>

<p>You can see the leak in progress using the Windows Task Manager, and just looking at how much memory exporer.exe is using in the Processes tab. Each time I created a new event in the Scooby prototype, the memory usage would go up, and it would never get released -- even if I left or reloaded the page. On my little XP laptop, IE initially takes up a little over 16 megs of memory, and I think at one point I had IE up over 80 megs with that leak.</p>

<p>I had to find the leak the old-fashioned way -- by reducing the called code to a smaller and smaller set until I could isolate the piece that was responsible. It was complicated by the fact that I'm trying to use that newfangled hash-style syntax in my code, and I wasn't sure what actually constitutes a closure in some cases.</p>

<p>Fortunately, I tend not to link from DOM objects to my JavaScript objects. Rarely I might create a script object property that points to a DOM node -- but as long as you don't do the reverse at the same time, you won't create the circular reference that sets up the leak. When you destroy the object, it can all get garbage-collected.</p>

<p>I'm really glad I thought to start testing for leaks early on in the process -- think about how evil it'd be trying to sort through all the reams and reams of UI code looking for a leak source. Makes me kind of queasy. So now, I guess any large changes or additions will require IE memleak testing. That's going to be a real pain in the ass, but I guess the alternative is much worse.</p>]]>
           </body>
           <title>
               <![CDATA[The old-fashioned way]]>
           </title>
           <publishedAt>2005-09-06T18:50:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-06-the-old-fashioned-way</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Of course now I find out that indeed even my relatively simple prototype for the Scooby week view leaks memory like a sieve in IE. Yeah, it had that allocated memory in a seriously vice-like deathgrip. Ah, such a joy.</p>

<p>After tracking down the offending closure (an event handler, natch), everything's solid again -- and you can bet I'll be a lot more careful even when I'm in 'blow and go' mode, roughing out a prototype like this.</p>]]>
           </body>
           <title>
               <![CDATA[Surprise, surprise]]>
           </title>
           <publishedAt>2005-09-02T14:38:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-02-surprise-surprise</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Doing a little reading today about <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ietechcol/dnwebgen/ie_leak_patterns.asp">memory leaks in IE</a> with complex JavaScript applications. I want to make sure Scooby's front-end code doesn't end up with any ugly, hard-to-track-down leakage. Does anybody know if Firefox or Safari suffers from this kind of stuff? I found <a href="http://www.bazon.net/mishoo/articles.epl?art_id=824">a really good post about this</a> from <a href="http://www.bazon.net/mishoo/">Mishoo</a> that does a good job of explaining the issue in plain English.</p>

<p>The problem is simply this:</p>

<blockquote>IE also, will detect and correctly remove objects creating circular references, except when one or more of those objects are DOM nodes or ActiveX objects.</blockquote>

<p>That, and of course -- closures. You gotta love IE. I have a new saying: "IE 6 is the new Netscape 4."</p>

<p>The MSDN mothership also pointed me also to a nice article explaining <a href="http://blogs.msdn.com/ericlippert/archive/2003/09/17/53038.aspx">how script garbage-collectors work</a>. Apparently JScript's GC is a 'nongenerational mark-and-sweep garbage collector.'</p>

<p>That was not terribly helpful to me until I could find out what a <a href="http://www.iecc.com/gclist/GC-algorithms.html#Generational%20collection">'generational' collector</a> is. Apparently generational garbage collection is "Based on the observation that most objects have short lifetimes, it is useful to restrict garbage collection to the most recently allocated objects." I was able to find that info, and a lot of other good stuff about GCs at the <a href="http://www.iecc.com/gclist/GC-faq.html">GC FAQ</a>.</p>]]>
           </body>
           <title>
               <![CDATA[Memory leakage in IE]]>
           </title>
           <publishedAt>2005-09-02T11:45:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-02-memory-leakage-in-ie</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Finally got a good <a href="/demo/scooby1.html">prototype page</a> (not using Prototype in it yet, but we'll get there) of an event 'lozenge' (as they seem to call it) for Scooby.</p>

<p>I've got the drag working properly (even in IE6, the problem child), and vertical resizing. It's currently only a single-day of events -- i.e., one narrow, vertical track.</p>

<p>The next step is to implement a snap-to (I guess in 15-min. increments?) for both the dragging and the resizing.</p>

<p>Looks like the guys at <a href="http://www.kiko.com/">Kiko</a> have gotten at a lot of this stuff working already. However, the way they have chosen to deal with overlapping events is not ideal -- hopefully taking the same approach Chandler does will be a tenable solution for Scooby.</p>]]>
           </body>
           <title>
               <![CDATA[Scooby steps]]>
           </title>
           <publishedAt>2005-09-01T12:31:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-09-01-scooby-steps</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>The main project I'm to be working on at <a href="http://www.osafouncation.org">OSAF</a> is <a href="http://wiki.osafoundation.org/bin/view/Projects/ScoobyHome">Scooby</a>, a Web-based CalDAV client. Part of my job is to evaluate the emerging AJAX toolkits to figure out which one we want to use. </p>

<p>So far, the one that looks best for our purposes is the unfortunately-named <a href="http://prototype.conio.net/">Prototype</a> toolkit ("Are you using Prototype in your prototype?" "Yes."), which provides the AJAX functionality for <a href="http://www.rubyonrails.org">Rails</a>. Despite all the irritating, relentless overhyping of Rails, Prototype seems pretty solid, and actually provides something reasonably close to direct access to the XMLHttpRequest object's API.</p>

<p>The Prototype guys seem pretty sharp, overall. Prototype uses that weird hash-based JavaScript syntax I'm seeing everywhere now, but the code seems pretty tight. However, having found a tiny little bug in the code that I wanted to fix, I looked at the process for contributing fixes, and was amazed at what I found. Check this out:</p>

<blockquote>To build Prototype, you'll need:<ul>
<li>a copy of the Prototype source tree, either from a distribution tarball or from the darcs repository (see below)</li>
<li>Ruby 1.8.2 or higher (http://www.ruby-lang.org/)</li>
<li>Rake -- Ruby Make (http://rake.rubyforge.org/)</li>
<li>RDoc, if your Ruby distribution does not include it</li>
<li>darcs 1.0.1 or higher (http://abridgegame.org/darcs/; static binaries available at http://www.scannedinavian.org/DarcsWiki/CategoryBinaries)</li>
</ul>
</blockquote>

<p>
Does this make any sense? All this crap for one, tiny .js file. Lucky for me, I already use Ruby, so I have most of this stuff, but that's probably not the case for a lot of folks.</p>

<p>On top of all the Ruby stuff, they also want you to install some alternative sourcecode version-control system, instead of just using S N. I'm sure Darcs is a perfectly fine version-control system, but we're talking about a JavaScript library here, people. Did I mention that it's one, single .js file?</p>

<p>Here's the process for submitting fixes:</p>

<blockquote>Modify the files in <tt>src/</tt>, add 
tests in <code>test/</code></pre> if possible, generate a new dist file, and record the changes with <code>darcs record -al</code></pre>. Then email patches to mailto:sam@conio.net using <code>darcs send</code></pre>.</blockquote>

<p>You can't even send the patch with a normal e-mail. I did mention that all this is for one, tiny .js file, right?</p>]]>
           </body>
           <title>
               <![CDATA[Prototype WTF]]>
           </title>
           <publishedAt>2005-08-25T11:37:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-08-25-prototype-wtf</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Okay, so this is a bit of a weird feeling. I'm sitting here having my morning cup of coffee, and reading <a href="http://blogs.salon.com/0000014/">Scott Rosenburg's Weblog</a> at <a href="http://www.salon.com">Salon.com</a>, and at the end of the entry, I see this:</p>

<blockquote>I always understood this intellectually, but now, after several years of following the work over at OSAF for my book, I feel it in my bones.</blockquote>

<p>I realize that this is the guy I was sharing an office/room with for a couple of days the other week when I was at the office. We introduced ourselves, and shook hands -- I guess I should pay better attention when I meet people for the first time.</p>

<p>I'll be interested to see how the book comes out.</p>
]]>
           </body>
           <title>
               <![CDATA[Kind of a weird feeling]]>
           </title>
           <publishedAt>2005-08-25T11:03:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-08-25-kind-of-a-weird-feeling</permalink>
</article>
       <article>           <body>
               <![CDATA[<p>Well, here we are. The first entry in this Weblog, <a href="http://www.fleegix.org">Fleegix.org</a>. It's intended to serve as a little bit of a window on the Web into my life.</p>

<p>So, who am I? Since this thing is still in the very embryonic stages, I have no profile up online here. So, in the interim, I guess I can point to the <a href="http://www.oreillynet.com/pub/au/2266">writer's profile</a> I have up on the O'Reilly Network site.</p>

<p>That should at least be a start, although the job info is out of date now. I've just started a new job at the <a href="http://www.osafoundation.org">Open Source Applications Foundation</a>. And I'm pretty damned excited to be working as part of the Great Open-Source Conspiracy. Go, team!</p>

<p>You'll see this site grow over time into something a bit more full-featured. The software behind the site is home-grown, written in the <a href="http://www.ruby-lang.org">Ruby programming language</a>. </p>

<p>I actually started to do this with <a href="http://typo.leetsoft.com/trac/">Typo</a>, a <a href="http://www.rubyonrails.com">Rails</a>-based Weblog application, but found the thing impossible to set up on my Ubuntu laptop. Nice that Rails is supposed to be so easy to use, but it's not exactly a dream to set up -- especially if you don't want to use <a href="http://docs.rubygems.org/">Gems</a>. And yes, I'm compiling Ruby from source, so it shouldn't be all that hard.</p>

<p>So, anyhow, I'm happy to offer you Fleegix.org, I hope it proves to be both interesting and useful.</p>]]>
           </body>
           <title>
               <![CDATA[Fleegix.org goes live]]>
           </title>
           <publishedAt>2005-08-24T18:33:00.000Z</publishedAt>
           <permalink>http://fleegix.org/2005-08-24-fleegix-org-goes-live</permalink>
</article>
</feed>
