Monday, December 03, 2007

Bindows Gauges

Recently, Bindows released a set of very functional gauges. These are "provided free of charge." They're built on top of their excellent Bindows component library.

The gauges are built from their BiGauge2 component.

One of the great things about these gauges is that it not only gives you a flavor of what Bindows can do, but that at least with these gauges, you don't need Bindows to manipulate them.

All you really need is the ability to set the value of the needle and the labels.

Here's an example. ( Make sure that you're running this in IE5.5+ or Firefox 2. The gauges won't show up in Safari ).

The two gauges respond to the mousemove event. The x or the e.clientX position and the y or the e.clientY position are updated on the gauges.

First, you'll need to get the gauges. Bindows has made this really easy. You need to download the gauge library and then follow these instructions.

Once you have them, you can manipulate the XML that defines the gauges. You can change the label, the start point, the end point, the ticks, etc.

However, those changes are static. What's more useful is to make changes at runtime. So, now, it's a matter of adding an event handler to manipulate the gauges.

In our example, we do two things --

1) Update the value of the needle with the new x/y position
2) Update the labels with the actual x/y position

The first is easy and is documented by Bindows. In our case, we do --

var xPosGauge = bindows.loadGaugeIntoDiv("gauges/gauge1.xml", "xPosGauge");
var yPosGauge = bindows.loadGaugeIntoDiv("gauges/gauge2.xml", "yPosGauge");

var xNeedle = xPosGauge.needle, yNeedle = yPosGauge.needle;

var handleMousemove = function(e) {
var x = parseInt(e.clientX);
...
xNeedle.setValue(x);
var y = parseInt(e.clientY);
...
yNeedle.setValue(y);
}

We get a reference to the gauge object, get the property "needle" and then at runtime ( in the mousemove event handler ) set it's value. The needle moves!

The second part is a little bit more difficult. I wasn't able to find a way to get to the labels without doing a "hack."

Through the magic of Firebug ( or Microsoft's Developer Toolbar ), we'll find out that the label is a BiGauge2Label.

Unfortunately, knowing that isn't really too useful. What's more useful is knowing where the second label appears in the structure of the gauge. By knowing that, we get a reference and can manipulate it.

This is why there's this strange looking code which locates the second label --

var xKids = xPosGauge.__gauge._gauge2Group.getChildren();
var len = xKids.length;
var ct = 0, xPxLabel, yPxLabel;

for (var i=0;i
if (xKids[i] instanceof BiGauge2Label) {
if(ct==1) {
xPxLabel=xKids[i];
break;
}
++ct;
}
}


Once we get the label, it's just a matter of setting it in the event handler --

var handleMousemove = function(e) {
var x = parseInt(e.clientX);
xNeedle.setValue(x);
xPxLabel.setText(x);
var y = parseInt(e.clientY);
yNeedle.setValue(y);
yPxLabel.setText(y);
}

The example uses the YUI Library to add the mousemove event, but you don't have to. You can use any library you want ( or not ) to handle the event.

To run my example, on your systems, you'll need --

1) The Bindows gauge library
2) My two gauges ( gauge1.xml and gauge2.xml )
3) My code ( and view the source )

That's it! Please update and improve. Enjoy!

2 comments:

Niclas Norgren said...

Very nice samples indeed!

Some additional insight:
you could add an id to the label and thereby making it available in the same fashion as the needle. Adding id=label" to the labels in the xml files (gauge1.xml & gauge2.xml), you could simplify your init method to the following:

function init() {
var xPosGauge = bindows.loadGaugeIntoDiv("gauges/gauge1.xml", "xPosGauge");
var yPosGauge = bindows.loadGaugeIntoDiv("gauges/gauge2.xml", "yPosGauge");

var b = document.body;
var handleMousemove = function(e) {

var x = parseInt(e.clientX);
xPosGauge.needle.setValue(x);
xPosGauge.label.setText(x);

var y = parseInt(e.clientY);
yPosGauge.needle.setValue(y);
yPosGauge.label.setText(y);

}
YAHOO.util.Event.on(b, "mousemove", handleMousemove);
}

skypoet said...

Niclas, you're absolutely right. Here's an updated version with your idea.

It really simplified the code and the core of it is clean --

function init() {
var xPosGauge = bindows.loadGaugeIntoDiv("gauges/gauge1b.xml", "xPosGauge");
var yPosGauge = bindows.loadGaugeIntoDiv("gauges/gauge2b.xml", "yPosGauge");

var xNeedle = xPosGauge.needle, yNeedle = yPosGauge.needle;
var b = document.body;

var handleMousemove = function(e) {
var x = parseInt(e.clientX);
xNeedle.setValue(x);
xPosGauge.clientXPos.setText(x);
var y = parseInt(e.clientY);
yNeedle.setValue(y);
yPosGauge.clientYPos.setText(y);
}
YAHOO.util.Event.on(b, "mousemove", handleMousemove);
}

Thanks again!