Saturday, April 12, 2008

One step forward in the great procrastinating adventure


Today I would have been writing zillions of pages on the upcoming "Learning Dojo" book from Packtpub. I have entertained a mild headache the entire week, and for reasons unknown I did some basic research instead. It was Dojo, though, but it was for some reason wildly game-related. Search me.

As it happens, in just a short few hours (if you can keep a secret, it's for a hex-based star empires / Traveller kind of free strategy game sitting comfortably upon google application engine. Please don't tell anyone, but I *really* like game programming, OK?

At the moment, I've just managed to make a couple of Dojo 1.1 widgets that looks like above
If you want to see the hexes magically react to your cursor, step up to ;
http://genericwitticism.com/ld/dojo-1.1b1/andbeyond/test.html

I've used dojox.gfx 2d magic, of course, but it still gets me back to the old days as a teenager, trying to get something cool up on a screen. I'm 41, but now I finally can :) [When you're 41, you're officially allowed to smile about it. Not everyone knows this]

Cheers,
PS

Wednesday, April 9, 2008

Floating labels for Charts in Dojo (dojox.gfx)

As I've written before, I have the opportunity to work as a consultant for a startup company which *really* want to do Ajax stuff. They want things to be decoupled, load asynchronously and show up as available and also emphasize charts and other graphics quite a lot.

Naturally the discussion has veered conspicuously towards flash and flex (which I detest for religious reasons) to give pizzazz and dynamic glamour to charts and whatnot in the overall customer experience.

Digging into dojox.gfx, I made several interesting discoveries which has made me keep the hounds at bay for the time being. Not that the following things aren't part of dojo (yet), but it's fairly simple to add (sort of :).

What I wanted to have, above all, was an animated label which shows the current value the mouse is onmouseing over, so that you can have a bar chart where you drag the mouse cursor over one bar after another and a label "floats" animatedly between the bars you choose, showing the exact value, pretty much as in Google Analytics (a popular comparison).

What I ended up doing was a two-fold approach. First I had to collect the "label" strings from the charts. I started out with the "Default" or Lines chart defined in dojox.charting.plot2d.Default;

An example of what I'm talking about can be found here; http://genericwitticism.com/ld/dojo-1.1b1/widespace/test_chart.html

Inside the render function, the markers for the charts are created (If you don't use markers for the chart, no labels are shown this way. So there). And I then added some code to save away the actual 'y' value for the marker inside the object for each marker, which was then stuffed into an array for later;

//------------------------------------------- ************ (1) ************ Add label info to the lpoly array to be collected later
if(typeof run.data[0] == "number"){
lpoly = dojo.map(run.data, function(v, i){
return {
x: this._hScaler.scale * (i + 1 - this._hScaler.bounds.lower) + offsets.l,
y: dim.height - offsets.b - this._vScaler.scale * (v - this._vScaler.bounds.lower),
label: v //------------------------------------------------------------------------------------------- Foo
};
}, this);
}else{
lpoly = dojo.map(run.data, function(v, i){
return {
x: this._hScaler.scale * (v.x - this._hScaler.bounds.lower) + offsets.l,
y: dim.height - offsets.b - this._vScaler.scale * (v.y - this._vScaler.bounds.lower),
label: v //------------------------------------------------------------------------------------------- Foo
};
}, this);
}

It's a bit sloppily done, since I've replicated the code twice, but I was tired, OK. :) As you can see, I've marked the new line in the code with the "Foo" comment.

Further down in the render method, the markers get created by use of dojox.gfx, which wraps a host of usefult 2d graphics api's and detects whether to use vml (IE) or svg (Everybody else (as usual)). Since dojo.connect can be used on graphical objects as well it wasn't difficult to add a callback function for onmouseover;

if(this.opt.markers){
//------------------------------------------- ************ (2) ************ Add callbacks with the collected label info
dojo.forEach(lpoly, function(c)
{
var path = "M" + c.x + " " + c.y + " " + marker;
//---------------------------------- >
var self = this;
var label = c.label;
function foofun(e)
{
//console.log("foofun called. e = "+e+", s = "+s+", label = "+label);
self._showMarkerLabel(e, s, label);
}
//---------------------------------- <
if(outline){
s.createPath(path).setStroke(outline);

}
var path = s.createPath(path);
path.setStroke(stroke).setFill(stroke.color);
path.connect("onmouseover", foofun); //---------------------------------- Foo
}, this);

}

Of course, this leaves out the magic function self._showMarkerLabel, which actually does the job. As things would have it, most Charts (not Pie, though) extends dojox.charting.plot2d.Base, where I put the remaining function(s);

,
_group: "", // group of marker shapes
//_markerLabel: "", // The 'flashy', 'floaty' marker label which will wow the crowd. Hurrah! :)
//_markerLabelShadow: "",
_labelText: "",
_curPos: "",
_oldPos: "", // Collect old positions for label, shadow and text
_showMarkerLabel: function(evt, surface, label)
{
label = label || "Foo";

var x = evt.target.x.baseVal.value;
var y = evt.target.y.baseVal.value;
var pos = {dx: x, dy: y-20};
var spos = {dx: pos.dx+2, dy: pos.dy+2};
var txtpos = {dx: pos.dx+7, dy:pos.dy+18};
this._curPos = {pos: pos, spos: spos, txtpos: txtpos};

if(this._group == "")
{
this._group = surface.createGroup();
}

if(this._labelText)
{
this._group.remove(this._labelText);
}

var txt = {width: 100, height: 30, text: label};
this._labelText = surface.createText(txt);
this._labelText.setFont({family: "Arial", size: "9pt", weight: "normal"});
this._labelText.setFill("black");
//this._labelText.setStroke("black");
this._group.add(this._labelText);

if(this._oldPos == "")
{

this.smoothMoves(this._curPos, this._curPos); // Gratitious call to shake loose initialization bug in fx
}
else
{
this.smoothMoves(this._oldPos, this._curPos);
}
// Save old positions
this._oldPos = this._curPos;
},

smoothMoves: function(oldPos, curPos)
{
var oldpos = oldPos.pos;
var oldspos = oldPos.spos;
var oldtxtpos = oldPos.txtpos;

var pos = curPos.pos;
var spos = curPos.spos;
var txtpos = curPos.txtpos;

console.log("smoothMoves called markerlabel = "+this._markerLabel+", labelShadow = "+this._markerLabelShadow+", text = "+this._labelText);
var a1 = dojox.gfx.fx.animateTransform(
{
shape: this._group,
duration: 100,
transform:
[
{name: "translate", start: [oldtxtpos.dx, oldtxtpos.dy], end: [txtpos.dx, txtpos.dy]}
]
});
}
a1.play();

I put all this at the end of Base.js in dojox/charting/plot2d, which did the trick. I had been playing with having a rounded label with a drop shadow, but can't seem to be able to offset the drop-shadow rectangle properly. If you know how to do this (within a group) , please mail or comment!

Cheers,
PS

Monday, April 7, 2008

Unified toolkit model

I had some time to spend with Ext this weekend, and it struck me that as nice as it looks, it still doesn't have a widget system. You might complain now since you can point me right away to a dozen or more nice-looking widgets that Ext sports. Yes, they're widgets, and yes, there's some system underneath it all, of course. I especially like the data modeling for the grid, et.c.

What I mean when I say that Ext has no widget system, is that there is no templating system in ext, and it seems like the only way of managing DOM interaction is to use jQuery-like stuff to add behavior and looks more or less manually.

When I create custom widgets in Dojo, I have the choice of using the standard ${} templating system, or the Django templating system. When I put a widget or two on the page, I have a number of magic functions that gets called by Dojo which enforces code sanitation in a good way. Also, when I need to change looks for the widget which is only related to styling, I change the client-side Dojo widget template and reload. I get the impression that a lot of styling issues gets hard-coded in Ext (and possibly jQuery as well) as hard to maintain document.createElement statements.

If this is the case, and Dojo has a truly outstanding widgeting system, why can't we share the love? I really like some features of the Ext grid, for example. But I'm really reluctant to create custom components without a client-side templating system. How hard could it be to us eone with the other?

Also, if that is possible, maybe one could make further concessions, and go all out for complete toolkit integrations :) Ideally, I'd like to use any widget from any toolkit (that behaves ...) together with any data model from another and wrap it in the widget model of a third (OK, Dojo).

Cheers,
PS