Tuesday, November 25, 2008

The power of Dojo i18n

I had said at an early stage that I was going to use Dojos i18n system to translate snippets of text in World Change Network. Now that the time came to actually implement it, I realized I had some learning to do to get all bits and pieces right. As it turned out, using Dojos i18n system for you own purposes is really simple.

If you take a look at the unit test for i18n at http://download.dojotoolkit.org/current-stable/dojo-release-1.2.2/dojo/tests/i18n.js you see that it uses three major tricks;

1. Load the i18n strings bundle of your choice using dojo.requireLocalization("tests","salutations",locale);
2. Get a specific bundle using var salutaions = dojo.i18n.getLocalization("tests", "salutations", "en");
3. Get the specific string for a given key using salutations['hello'];

Let's check the arguments for number (1) and (2; Only the first two are needed, which describe the dojo package to look for bundles in and the name of the bundle. If you want to specify another locale than the one the browser declares, it can be added as third argument, "sv" for Swedish, when the browser would say "en-us", et.c.

All well and good, but where do we put our different version of strings? As it turns out, in the dojo/test directory a directory named 'nls' can be found. In the root of that is a file called 'salutations.js'. This is the default key-value translation that i18n falls back on if the locale cannot be found.

Then comes a host of subdirectories ; zh, nl, il, dk, de, et.c et.c., one for each locale (that you want or can define). In each of these is a separate 'salutations.js' containing locale-specific resources.

The file format look like this;

{
it: "Italian",
ja: "Japanese",
ko: "Korean",
......
hello: "Hello",
dojo: "Dojo",
hello_dojo: "${hello}, ${dojo}!",
file_not_found:"The file you requested, ${0}, is not found."
}

for the default file, and like this in the 'it' subdirectory;

{
it: "italiano",
hello: "Ciao"
}

And that's it.

I began creating a small naive custom widget, which subtituted the content of the element where it is declared with the localized string found for the content used as key. It's not very fast, but simple to understand and use.

dojo.provide("layout.translate");

dojo.require("dijit._Templated");
dojo.require("dijit._Widget");
dojo.require("dojo.i18n");

dojo.declare("layout.translate", [ dijit._Widget ],
{
widgetsInTemplate : false,
string : "",

postCreate: function()
{
if (!this.string)
{
this.string = this.domNode.innerHTML;
}
console.log("postCreate for layout.translate called. locale == '"+dojo.locale+"'");
dojo.requireLocalization("layout", "salutations");
var res = dojo.i18n.getLocalization("layout", "salutations");
console.log("Translation key was '"+this.string+"'");
var str = res[this.string];
this.domNode.innerHTML = str;
}

});

Note that I just copied the whole nls directory from dojo/test for my own uses, and edited the files, leaving the original filename intact, just in case :) A better way of utilizing i18n would be to have a base class for all custom widgets, which read in a i18n bundle, and injects all keys into each class, so that every subclass has a lot of this._i18n_command_delete (If we have a naming convention that let all i18n keys begin with '_i18n_' for example).

Then we could have all custom widget templates just sprinkle their markup with a lot of ${_i18n_command_delete} and so on, which would pull in the current value of that 'this' property of the widget when it is rendered in the page.

Hmm....

Come to think of it, it seems to be possible for this to be put inside dijit._Widget, or possibly _Templated, which would make it spread to all custom widgets automatically. The only thing needed would be to prepend '_i18n_' to all key names, so that 'command_delete' inside a bundle file would become this_i18n_command_delete in the widget.

One would also need to have a convention that this only worked if the developer put a 'nls' directory under the package directory where widgets of a certain package are declared, following the order declared earlier.

Actually, this would be a pretty neat idea. Just my fault for using a blog post instead of TRAC to add feature requests! Oh, you mean I could do it myself? OK, I'll add it to the queue :)

Cheers,
PS




Monday, November 17, 2008

Codebits 2008









Last Wednesday I flew down to Lissabon to attend and talk at the SAPO Codebits conference. I had a really great time, meeting a lot of people I've only tweeted or mailed with before.

As always, Lissabon is a treat. People are helpful and very respectful. A colleague made a very spot on question today when I told him about the trip: "Would you like to go back there again soon", to which I would empathically answer Yes! :)

Many times, when you've spent a couple of days in a city you get kind of fed up on the experience, but Lissabon is not one of those towns.

It didn't hurt one bit that I left a cold and rainy Stockholm landing in a sunny and warm (17-20 degrees centigrade) Lissabon.

The Hotel (Galé 'Opera') and the venue were located in an area just alongside the 'Docas', an hours walk or so from the city centre but with a lot of rustique ambience all of its own.

I had so many things to attend to before leaving that I was only partially read up on the conference and my fellow speakers. It turned out that the conference was much larger that I had anticipated with a host of Portugals finest hackers.

In many ways the Codebits conferenc felt like Google I/O; A lot of multi-coloured couches, interesting lighting, free soda and coffee and the ability to turn to _anyone_ at random and strike up a conversation which revolved around important and interesting things, with the person in questions be able to understand you and bring his or her own into the discussion like nothing to it.

One of my personal surprises was that Mário Valente, who I knew only as a very smart person with a stupendously correct view of the current trends in web development, as well as a extremely decent Python and JavaScript hacker. It turned out he started Portugal's first ISP as well as a couple of other successful ventures - and is also in the middle of something bigger, more of which perhaps later..

We had been planning on doing some SSJS hacking during the conference but I got entangled in some late minutes changes to my book and Mário had both teaching and business issues to attend to, so it reamined a very good idea. Mário had some really good inpout on the current problems of Server-Side JavaScript efforts; 1) There's no 'killer' framework (yet) for SSJS, 2) If one were to create on, it would not be portable, due to the fact that the system APIs that RHino exposes are not the same that Spidermonkey (for example) does.

So we were thinking along the lines of arranging for a standard SSJS low-level API, based on the Java-APs exposed by Rhino (Mário's idea) so that SSJS implementors would have a stable platform to work from.

Also we're planning to do a thorough survey of the cloud or no-cloud SSJS frameworks available today to rank and get inspired by best-of-breed features.

My talk? It went OK. I managed to miss speaking to anyone in charge which meant I didn't get a headset, which meant I had to hulk under my 20.1 Inch portable Acer 9920, due to the fact that the only other mic was welded to the pulpet.

No worries though. Expect that I had the wrong settings for the TV-out in Kubuntu and had to turn my head for every slide to orient myself, having no other feedback on the screen. And I got a call in the middle, having forgot to turn off my phone, but other than that, sure things went OK.

I also had a great time speaking to Jan Lehnardt from CouchDB about REST, Dojo, Erlang and (of course) CouchDB.

On the speakers dinner I happened to sit across Mitch Altman who had a great number of things to say on all subjects possible, from electronics, dairy products and Brian Eno to art, music, war and interesting people in general. I tried to chip in with some good comments and since this is as good time as any, the books I spoke about was 'My war gone by, I miss you so' (horrible title, one of the best books I've read - not nearly as gory as you might think) by Anthony Loyd, A year of swollen appendices by Brian Eno and On a faraway beach by David Sheppard.

Another member of the table proved to have alarmingly good knowledge of the inner workings of russian botnet 'corporations', the current evolution of 'black' insurance and business agreements concerning buying and seelling botnet services, the 'double-NAT-with-homebrew-VM' solution of todays malware containers and the trend towrds the botnets becoming more of a symbiotic affair from the earlier parasitic standpoint, what with the automatic patching and maintenance that must be provided to ensure smooth runnings. A horror ride, to be sure, but not the less fascinating for that.

Actually, I spoke to so many, most of you had no cards, but please mail me if you want to stay in contact (my address is to the side on this page).

In all I met an enourmous amount of friendly and interesting people (Celso, João, Jack and everyone else) that it'll probably take me weeks to sort out the experience.

Thanks a lot to everybody involved!

Wednesday, November 5, 2008

A reasonably complicated custom Dojo widget example


I get a lot of questions from people on how to do this and that with Dojo, sometimes very specific and sometimes about how to approach problems in general. I don't really consider myself experienced to speak about all things Dojo, I'm actually just more of a fanboy.

Most of my answers, though, boil down to some basic things, were the most common is : make a custom widget. This is key, but seemingly missing from many frameworks/toolkits today. I feel like there has been three kind of 'generations' in JavaScript usage in the browser in recent years, and many of the flame-wars and misunderstandings might be due to the fact that people have a lot of misaligned assumptions when speaking of JavaScript programming. In my view the different generations or stages has been the following;

1. JavaScript inlined in the page - Netscape 4/ IE3 kludgery [Animal House - foodfight scene]
2. Clean html with consistent and meaningful styling and classifications with all JavaScript logic in a couple of separate files which operate on said markup, transforming it, attaching event handlers, et.c. - jQuery [2001 - space shuttle approach to twin-wheel space station].
3. Client-side hierarchical components with modularized logic and templates - Dojo [Basic Instict - the single crotch frame].

First of all I'd like to say that jQuery might have a modularized templating system, where you separate widget markup from logic - I'm not experienced enough in it (yet) to tell. Please comment if you have some good references. Then I'd like to say that both Ext and JavascriptMVC has excellent templating systems for their components - in a very similar vein to what Dojo has (again, AFAIK). But I had to choose one good example out of each group, or at least it felt that way.

What do you gain by writing custom components all the time? It seems awfully complicated, doesn't it?

OK. what do you gain (in Dojo). Let's see;

1. You get an enforced structure that help you separate view and logic inside the widget.
2. You get opinionated support from the framework for automatic id generation, coupling markup elements to widget references and widget lifecycle management (certain named functions get called at certain times).
3. You get _guarantees_ that the widget is hermetically sealed, unless you do something completely stupid. This means you can take it out from one place and put it somewhere else, or change your mind about having three and putting in four instead. No colissions, no overlaps.
4. Widgets markup html snippet templates can themselves (at least in Dojo) contain other generally arbitrary widgets,. Turtles, all the way down, basically.
5. The whole mélange can be expressed in the HTML file that is actually loaded by the user with one (1) div.


But other than that, I suppose, not much.

Since I really only know Dojo, I will be using that in my example. Let's say that I want to have a widget with dynamically generated JavaScript-only 2D charts, where the charts can be dragged and dropped and reordered just like iGoogle or similar pages. Wouldn't that be cool?

Let's start with the target HTML file, which look like this:





I begin by loading some Dojo CSS stuff and the actual toolkit base itself from AOL's CDN (Google would have worked as well, of course). Then I have to configure the djConfig variable a bit so that Dojo find the local files for the widget referenced later, even though it is loaded cross-domain.

The dojo.require statements check if the referenced classes are available, and if not resolves them and load them (since the custom component 'multichart.main' is not part of dojo, I needed to point out where to find it in the modulePaths setting in djConfig earlier.

Then as just one, albeit fat, div tag, I define the draggable multichart container. As you see dojo uses custom HTML properties to let its parser instantiate widgets declared in markup (All widgets can also be created programmatically in the classical style, of course). the dojoType property declare a widget which must be loaded already. All other properties after that are inserted as 'this' properties of the instantiated widget class, if it has declared those names already. Works smoothly, truly.

I basically just pass one argument which is an associative array of names and values. The idea is that the names become title string on the charts, and the values point out urls where json data is provided to generate the charts.

The test file foo.txt looks like this:

{
series:
{
series1: [{x: 1, y: 0.2}, {x: 2, y: 0.5}, {x: 3, y: 1.2}, {x: 4, y: 0.3}],
series2: [{x: 1, y: 0.5}, {x: 2, y: 1.0}, {x: 3, y: 0.9}, {x: 4, y: 1.7}]
}
}

So nothing magic, just a json object with a property 'series' and one or more series of numbers, following the standard way of feeding the dojox.chart API.

But back to the custom widget. Since I declared that Dojo should look for widgets beginning with 'multichart' in the directory of the same name in the directory that the HTML file was loaded from, I place a file called 'main.js' there. Which looks like this;


dojo.provide("multichart.main");

dojo.require("dijit._Templated");
dojo.require("dijit._Widget");

dojo.require("dijit.layout.ContentPane");
dojo.require("dojox.layout.GridContainer");

dojo.require("multichart.chart");

dojo.declare("multichart.main", [ dijit._Widget, dijit._Templated ],
{
templatePath : dojo.moduleUrl("multichart","templates/main.html"),
widgetsInTemplate : true,

content : {}, // name - url pairs to make draggable charts out of. Must be passed from calling script / page
columns : 3, // How many columns we want to have in the GridContainer

constructor: function()
{
console.log("constructor for multichart.main called");
},

postCreate: function()
{
console.log("postCreate for multichart.main called mycontainer is "+this.test);
this.gc = new dojox.layout.GridContainer(
{
nbZones: this.columns,
opacity: 0.7, // For avatars of dragged components
allowAutoScroll: true,
hasResizableColumns: false,
isAutoOrganized : true,
withHandles: true,
acceptTypes: ["multichart.chart"] // This property must always be present, and can take any kind of widget, including your own
}, this.test);
this.gc.startup(); // When creating some dojox widgets programmtaically, you must manually call the startup() function, to make sure it's properly intialized
var i = 0; // Count for which column we'll place each chart in
var p = 0; // Count for which row we'll place a chart in
for(var name in this.content)
{
var url = this.content[name];
var chart = new multichart.chart({name: name, url:url}); // Create a custom chart with the given name and url
console.log("adding chart "+chart+" to zone "+i+", place "+p);
this.gc.addService(chart, i, p); // Add the chart to the GridContainer (This function will be called addChild in the future, for conformance with similar containers.
i++;
if (i > this.columns-1) // Go to next row if we've hit the end of the columns
{
i = 0;
p++;
}
}
}

});

It begins by telling Dojo that it contain the class 'multichart.main', then follow a lot of requiremenets which otherwise would have to be present in the main HTML file. Then follows the widget class declaration.

As you can see it inherits from two superclasses; _Widget which contain the widget subsystem logic and _Templated, which managed html template snippets.

Note the 'content' and 'columns' properties which, since they are defined here, can be passed from a markup declaration(or from a programmatic creation where the arguments gets passed in an object literal as first argument to the constructor). This also gives me a good place to put default values which will stand if not overwritten (such as 'columns').

postCreate gets called when the widget is ready for action, and here is where I usually put most of my init code. What this widget does is to create a Dojo component which mimics an iGoogle page and let the user drag, drop and rearrange all other Dojo widgets inside it. Then it loops over the argument and create any number of yet another custom component, 'multichart.chart', which is also present in the same directory.

Each widget which derive from _Tenplated can also define a html template inside a string or in an external file. I usually use external files when developing, and then use DOjo's offline build system to inline templates, compress, concatenate files inot one, et.c.

If you want to se the widget in action for yourself, you can download it as an archive here. You might also be interested in my upcoming book "Learning Dojo" where it it explained more fully, along with numerous other examples :) OK, I admit it, this whole post was mostly a shameless plug for the book, but partly I wanted to define the playing field a bit as well.

Cheers,
PS

Sunday, November 2, 2008

How to define a front-end developer

Devoting myself (or allowing myself to be dragged away by the carneval in childish glee) to Ajax and JavaScript the last years has changed the way I've looked at the composition of software teams and of projects. Today, the breakdown is glaringly obvious to me. But since it is the result of a kind of private mental jorney what is obvious to me need not be so to someone else.

I'm talking about the emerging role of the front-end developer, of course. Big deal you might say, I know what that guy does, but I'm not completely sure that everyobdy agree on that, hence this post.

In the days of yore, what you did on a computer was program, period.  Then came specializations of different kinds, like a dot painted on an expanding baloon becomes a circle. And still the expansion continues.

The traditional breakdown of duties in web-related projects has been in browser-specific things and server-specific things. That's actually very good, since this breakdown at least in part acknowledges the client as an entity. The role of the front-end (browser) team has been to create and manage the design and looks of the application, whereas the back-end team create and manage _all_ application logic, including client states (open trees, selected tabs, et.c.).

The front-end team was to be called designers, with en emphasis on producing HTML/CSS templates and all the Photoshop magic required for the quiltwork of images needed to give an illusion of a real application.

Later on these designers were asked to do some dynamic scripting to produce effects of various kinds, effectively becoming programmers in a way, even though their original vocation was that of esthetics and visual design. I don't say you can't mix the two,I'm just saying that in my experience the two fields draw two different personalities.

And on the other end, since the server-based frameworks need to slice, pickle and transform the provided templates into something that their server-side templating system can use, they get exposed to a lot of borderline design descisions, which is not something they originally signed up for either.

The result is that there is suddenly a risk that people are required and/or forced to make decisions and produce work for which they have both a minor talent in and doesn't really feel like, personally.

But that is a dicsussion of whether or not to use Thin Server Architecture (or any of its synonyms and special cases), so let's assume that we have a sane architecture with a cleanly separated front-end and back-end (REST or RESTish, preferrably), how do we look for talent in this brave new world?

Looking at ads for front-end developers shows a plethora of confusion. First of all the same kind of job might be defined as a designer, UI expert, Ajax developer, front-end programmer, Web designer, JavaScript programmer or any permutations thereof, many of which can be applied to a true designer role as well.

Looking at the skill set that the front-end developer should have we find that he or she must be a veteran of all major US armed conflicts since WWII, be able to design, build and fly a commercial airliner, have discovered at least three different cures for cancer (of which at least should have received the nobel price in either of Medicine, Physics or Chemistry) and also be the founder of two or more major schools of painting, including cubism.

It seems that people are both a little desperate and a little confused. Let me try to make things clearer.

In todays world, we need to have a good designer. The word designer will only be used in a classical sense, i.e. visual design. Skill-set: HTML/CSS, Photoshop/Gimp/whatnot, Usability, Fonts, Color theory, et.c.  Secondary skills: JavaScript, HTTP, Networking fundamentals, some Server-side language.

Then we have the elusive front-end developer. Skill-set: HTML/CSS, JavaScript, Ajax, , HTTP, Networking (latency, routing, distributed storage and processing, security), REST, XML (to argument against its use), SOAP/WSDL (see last comment). Secondary skills: Usability, some Server-side langauge.

The only changed thing with the skill-sets for the back-end team is that they no longer are forced to understand HTML/CSS and a smattering of JS, since there is no longer any server-side templates to massage.

On of my pet peeves is that there is an architect onboard, but he or she has launched the project without many times even decided on which Ajax toolkit to use. It's comparable to launching a project without having specified which back-end to use (Java? Python? Perhaps SSJS?).

Granted, in many cases the project has _not_ launched and the ad is for someone to come in as a front-end lead for the very prupose of evaulating and recommending technologies to use in the client layer, but there's still enough 'wild card' ads out there to make my hairs stand on end (all three of them).

Ok, rant over. I guess what I want to say is that the world is getting larger and more detailed at the same time, and that if you are searching for talent, you have better know what you are looking for, and take the time to be as specific as you can.

Cheers,
PS