Monday, February 26, 2007

Javascript Modules Revisited

For those of us who retch at the mention of both "Java" and "Javascript", today's post brings us deeper into my realm of insanity, "deep in the shit", to quote Colbert. Yes, it's no picnic, but the development world has its human moments. Moments where hubris, playful cynicism, and violent indignation must give way to humility. People, harken to my words, hidden among the copious piles of refuse, there's some good code in Dojo.

Don't run off and commit resources to it; I'm just saying it's a good read for someone looking for snippets to steal. If you need something that works today, it might be a good option, but hold your horses; I haven't finished reading the alternatives.

I've mentioned that Dojo has a module system. It plainly doesn't meet our needs. Let's be explicit about our requirements

Module system must:

  • be the first and only Javascript file explicitly loaded with a script tag in the header of a document
  • have a light footprint on the global context object (window in browsers), ideally one function
  • isolate each module in its own closure
  • isolate each module with its own context object, preferably the module object
  • leave no conditional module management code to users
  • provide singleton module objects that are loaded once per page
  • provide modules as shallow objects, encouraging the library user to obey the "Law of Demeter"
  • handle synchronous and asynchronous pattern interface
  • permit the library user to require a module under any pseudonym it desires, or vaguely, provide the flexibility of Python's import syntax, with suitable analogs for import module, import module as m, from module import *, from module import part as p.
  • permit the library user to move an entire directory of scripts without breaking any of its references to other modules within the same directory tree nor break references to global modules

Dojo does not appear to follow all of these edicts. For example, all modules use the global object, window, as their context object. Every top level module, dojo for example, leaves a footprint on the global object. Dojo encourages Demeter violations like, dojo.component.subcomponent.WhatYouReallyWant. The list of annoyances goes on.

However, Dojo does load modules synchronously, ironically with the so called "Asynchronous XML HTTP Request". My solution in Cixar Javascript, modules load asynchronously using DOM or write tricks. Modules register themselves when they're text loads. Register isolates the context object and closure.

Neither my solution nor Dojo's solution address the problem of mobile libraries. This is a critical feature for a real module system, since it would permit authors across the web to isolate a tool in a directory and permit users to place and name that directory anywhere and any way they want without having to modify the contained code.

The problem with my system was that it requires modules have to register their location:

this.register('module.js', function (module) {

This was necessary because of the non-blocking, asynchronous module loader. There was no way for a Javascript to recognize what module it was supposed to be since the module scripts would load in an indeterminate order.

Enter Dojo's module loader code. This bit of AJAX is pretty good, with lots and lots of embedded knowledge of multiple Javascript environments and their eccentricities. Using it as a reference, I wrote a new module loader system that provides both synchronous and asynchronous forms for require, and obviates the need for register calls completely.

A module:

/* import module */
var module = require('module.js');

/* import module, asynchronously */
require('module.js', function (module) {
});

/* import module as m */
var m = require('module.js');

/* from module import * */
with (require('module.js')) {
}

/* from module import component */
var component = require('module.js').component;

/* from module import component as c */
var c = require("module.js').component;

Most of all, the register function no longer exists. Modules have their own closure and singleton context object. Modules have their own require function so (eventually) they will be able to load modules relative to their own URL rather than the URL of the containing page. Here's what it looks like:

(function (url) {
var require = function (subUrl) {...};
eval(http.requestText(url));
}).call(modules[url], url);

Meanwhile, I also re-imagined Dojo's HTTP request mechanism, the heart of AJAX. Since the module system requires HTTP requests, it creates a pseudo-module that users can later require as http.js. The HTTP module supports the same abbreviated syntax for both synchronous and asynchronous requests as require, and provides forms for retrieving the HTTP response, text, XML, and the XML document element object. The module includes most of Dojo's code paths for multiple browsers, environments, and platforms and provides a wrapper for the HTTP response object that cleaves more strictly to an observable style and handles some odd cross browser cases.

var text = http.requestText('text.txt');

http.requestXML('xml.xml', function (xml) {
});

var response = http.request('location.html');
if (response.isOk()) {
var text = response.getText();
}

Sunday, February 25, 2007

Photo Rally 3

Ministers of Mayhem Patrick Thomas and Zach Unlastnamed held the third quarterly Photo Rally this weekend and it was my pleasure to attend for the first time. I captained "Team Moof" with our totem/mascot/team-mojo, Sam, with friends Tom Tarn, Jim Strange, and Kyle and Jen Wiens. We garnered second place and had a positive blast.

So, a photo rally turns out to be a scavenger hunt for photographs of vaguely described objectives for eight hours. Here are some some of my favorites from our collection.

From the first category of objectives "Adjectives A to Z"

Brutal

Divine

Guilty

Kosher

Questionable

Victory

Wicked

53. Chicken

"Show everyone, once and for all, why the chicken crossed the road. (5/3/2 points)"

36. Drive Thru

"Order something from a drivethrough while riding in a contraption that makes the window lady call for backup. Document your escapade. (8/5/3 points, have it your way)"

55. Flying

"I feel like I'm flying! (5/3/2 points)"

30. Uniform

"The Photo Rally Committee would like to take this time to remind you that you are not a unique and beautiful snowflake. Show your solidarity with matching team uniforms and crushed souls. (7 points)"

51. Mother's Birthday

"Today is my mother's birthday - true story! She couldn't make it , so you should do something nice for a different United employee instead. Also, please don't get arrested by the TSA. (6/4/2 carry-on points)"

52. Urban Kayacking

"Urban kayacking. Best sport since spooling. (7/4/3 points)"

43. Claim a Table

"Have your team claim a table at a restaurant. This should be performed with the same level of enthusiasm as claiming Iwo Jima. (8/5/2 points)"

49. Ghost Ridin' the Whip

"Ghost ride the whip in something that is most definitely not a car. (6/4/2 points)"

Monday, February 19, 2007

Squirrel

Today brings us Squirrel and Sand Witch, President of Dys

Squirrel

Today brings us Squirrel and Sand Witch, President of Dys

Tuesday, February 13, 2007

Parametric Art

I've been meaning to make some "parametric art" for some time now, and having worked on Tale graphics automation, I now have the tools I need. Parametric art is the name I'm using for creation of artistic compositions where the position, orientation, and shading are programmed using what we learned in High School trigonometry by the pseudonym "parametric equations". Last night I decided to attack the problem by making another set of backdrop images for Jason Reinsvold's Bowmaster. I popped open Inkscape, created some layers for sky, sun, moon, and terrain. Instead of hand positioning the Sun and Moon, I just put them on the origin. Then I pulled up my Python SVG tools that I made for generating maps. Using some trig, I programmed the positions and rotations of the sun and moon. Here are some samples:

more

Tomorrow's project is adjusting the linear gradients that overlay the cells in the foreground terrain to catch the light of the sun, moon, sky, or form shadows and silhouettes.

Sunday, February 11, 2007

New Character Sprites

I completely recreated the rider (or stand-alone character) for the Tale sprite graphic. The major goal was to represent both genders equally in the game. On the way, I created several hair styles and facial expressions, articulated the arms into three positions for each gender, and created a lot of layers. Here's the breakdown:

  • male or female
  • round, oval, or angular head
  • arms out stretched, bent for holding shields and such, or hanging at your sides
  • shirt with detachable sleeves
  • pants or shorts
  • shoes, boots, or sandals
  • buckler, roman shield, hero shield
  • long or short, lobed or round ears
  • 11 hair styles
  • 14 facial expressions

Here are a couple samples of riders:

Portraits

Hey folks. I've been down with the Flu, but I'm getting back in the saddle.

Saturday, a week ago, I stayed up late agonizing about a color module for Cixar Javascript. The new color module builds on the refinement of the Mootools color module and the Cixar Javascript type system. The new Color type provides accessors and mutators for HSL and RGB components and can parse hex strings in both modes. The color also tracks opacity. Under the hood, the Color instance is modal, converting its internal components array to arbitrary modes, radices, and cardinalities. For example, when you parse a six character RGB string, the color implicitly switches to base 256 with values in [0, 256) in RGB mode. When you set its lightness to .5, the color implicitly normalizes its components to HSL mode with values in [0, 1]. When you get the RGB string out, it actually doesn't do a conversion, but makes a copy of the color and converts that to RGB 256 mode so that you don't get floating point propagation error. The color modules is here. I still should port the "invert" function and find a way of consistently calculating "strobes" and "complements", but first I need to beat the definitions out of an art major (easy), but first I need to find a math major who knows some math (hard). All in all, this was a nice diversion, but I don't know whether I'll ever use it and I certainly stayed up too late working on it and fell ill.

I've continued my perusal of Javascript libraries. I started looking into uses for the new canvas tag that debuted in Safari and made its way into Opera and Firefox. Internet Explorer doesn't support the standard, but I found an open source library that Google has contributed to the community called excanvas that transparently causes canvas tags to mostly work in IE. The library performs some VML voodoo and provides an interface consistent with the canvas standard. The interface supports rotation, translation, and turtle drawing, but does not support gradients. I starting paring out pieces of the implementation into a matrix module for Cixar Javascript that provides a Matrix type with Google's matrix multiplication written elegantly and, alas, sub-optimally. Before I pare it out in favor of fast native loops, here's the pretty version:

return matrix.Matrix(
 each(range(value.getWidth()), function (x) {
  return each(range(other.getHeight()), function (y) {
   return sum(each(range(value.getWidth()), function (a) {
    return value[x][a] * otherValue[a][y];
   }));
  });
 })
);

Tale News

I'm redrawing the rider graphic for the sprite. This is the character sprite that will appear on maps, in battle mode, and close up in your inventory or equipment viewer. Additionally, the sprite will provide a small portrait for chats and status messages about your character. The portrait will have interchangeable faces to reflect your mood and also serves as an emoticon. Also, the primary goal in the redraw was to provide male and female variations of the character. So far, I've made the two figures, three arm positions each (outward, bent, and down for holding various armaments), three head shapes, several faces, many hair styles including "lemming", "block", and "dreads", and four kinds of ears. I've also outlined some clothes. Until the whole ensemble is ready, here are some samples for each of the facial expressions:

Thursday, February 1, 2007

Javascript Libraries

I've been poring over Javascript libraries lately, trying to ascertain the extent of their features, how much implementation overlap there is among them, and which ones implement certain features best. The idea is that I'm going to integrate the best tidbits into Cixar Javascript. I'm reading:

Please contact me if I need to add a library to my reading list.

I've got some general impressions so far. Dojo and Mochikit are by far the heaviest. They're loaded with lots and lots of well tested unreadable undocumented components. Dojo supports its own weight because it's the only Javascript library that has a module loader, albeit a module loader that loads modules into the global name-space. YUI, Mootools, and Scriptaculous are comparatively higher quality but smaller and limited to their size by the lack of a good module system. YUI is the best documented, having lots of Javadoc style comments. Mootools, I think proves to be the highest quality code for the few things it does and does rather well. Scriptaculous and its base library Prototype, spun off the Ruby on Rails project, both seem to work pretty well, but the code is criminally bad, showing lots of signs of having been designed by whim. I get a very strong "the least that would work" vibe from it.

Dojo's module system intrigued me because it loads modules synchronously with AJAX and Javascript's eval. I've considered applying the same ideas for Cixar Javascript's module system. However, the current Cixar Javascript module system puts the power of nomenclature into the hands of the module writer, not the hands of Kurremkarmerruk, the Wizard who knows and manages all (or most) of the names in the universe. I think that the "CJS" syntax is verbose because of this feature, not because it loads modules asynchronously. Since loading modules asynchronously may have higher performance in the long run, I don't see much reason to adopt Dojo's approach. However, Dojo does include a lot of good snippets that seem to embody a lot of working knowledge on how to make Javascript work in many, many environments, so I do intend to study it throughly.

Let me back these statements up with some code. This is the Dojo syntax for defining, loading, and using a module:

dojo.provide('dojo.provided_module');
dojo.require('dojo.required_module');
dojo.provided_module.provision = dojo.required_module.provision;

This is Cixar Javascript's:

this.register('cixar/provided_module.js', function () {
this.require('cixar/required_module.js', function (that) {
this.provision = that.provision;
});
});

I particularly like using Javascript's with block to effectively bring all of a module into my name-space so that I don't have to qualify any of its names.

this.register('my.js', function () {
this.require('javascript.js', function (js) { with (js) {
assertEq(js.List, List);
}});
});

I'm getting comfortable with the parentheses and braces because I feel that localizing names is really important for the long term maintainability and extensibility of the world of Javascript.

From this preliminary analysis, I think I will be integrating most of Mootools code since it's small and high quality. I will probably also integrate parts of Dojo and Mochikit since their feature coverage is quite extensive, but porting whole modules is probably out of the question. In any case, I will try to bring a comprehensive set of features into CJS so that people coming from any of these frameworks will find some degree of familiarity, if not because of their experience with their respective Javascript libraries, then because of their familiarity with the server side scripting language on which that library was based.