ChartDirector Ver 3.0 (Perl Edition)

Javascript Clickable Charts




This example demonstrates how you could use client side Javascript with ChartDirector's image map features.

In this example, a clickable area chart will be produced. Apart from responding to mouse clicks, the area chart will display in real time detail information about the data points when the mouse moves over the areas in the chart. It is accomplishing by using "onMouseOver" and "onMouseOut" event handlers with client side Javascript and dynamic HTML.

The code for this example is listed below.

[The following is available as "perldemo_cgi/jsarea.pl".]
#!/usr/bin/perl #Include current script directory in the module path (needed on Microsoft IIS). #This allows this script to work by copying ChartDirector to the same directory #as the script (as an alternative to installation in Perl module directory) use File::Basename; use lib dirname($0); use perlchartdir; # #For demo purpose, we use hard coded data. In real life, the following data #could come from a database. # my $revenue = [4500, 5600, 6300, 8000, 12000, 14000, 16000, 20000, 24000, 28000] ; my $grossMargin = [62, 65, 63, 60, 55, 56, 57, 53, 52, 50]; my $backLog = [563, 683, 788, 941, 1334, 1522, 1644, 1905, 2222, 2544]; my $receviable = [750, 840, 860, 1200, 2200, 2700, 2800, 3900, 4900, 6000]; my $labels = ["1992", "1993", "1994", "1995", "1996", "1997", "1998", "1999", "2000", "2001"]; #Create a XYChart object of size 440 x 200 pixels my $c = new XYChart(440, 200); #Add a title to the chart using Times Bold Italic font $c->addTitle("Annual Revenue for Star Tech", "timesbi.ttf"); #Set the plotarea at (60, 5) and of size 350 x 150 pixels $c->setPlotArea(60, 25, 350, 150); #Add an area chart layer for the revenue data $c->addAreaLayer($revenue, 0x3333cc, "Revenue")->setBorderColor( $perlchartdir::SameAsMainColor); #Set the x axis labels using the given labels $c->xAxis()->setLabels($labels); #Add a title to the y axis $c->yAxis()->setTitle("USD (K)"); #Create the image and save it in a temporary location my $chart1URL = $c->makeTmpFile("/tmp/tmpcharts"); #Client side Javascript to show detail information "onmouseover" my $showText = "onmouseover='setDIV(\"info{x}\", \"visible\");' "; #Client side Javascript to hide detail information "onmouseout" my $hideText = "onmouseout='setDIV(\"info{x}\", \"hidden\");' "; #"alt" attribute to show tool tip my $toolTip = "title='{xLabel}: USD {value|0}K'"; #Create an image map for the chart my $imageMap = $c->getHTMLImageMap("xystub.pl", "", "$showText$hideText$toolTip" ); print "Content-type: text/html\n\n"; print <<EndOfHTML <html> <body> <h1>Javascript Clickable Chart</h1> <p><a href="viewsource.pl?file=$ENV{"SCRIPT_NAME"}"> View Source Code </a></p> <p style="width:500px"> Move the mouse cursor over the area chart to see what happens! This effect is achieved by using image maps with client side Javascript. </p> <img src="myimage.pl?img=/tmp/tmpcharts/$chart1URL" border="0" usemap="#map1"> <map name="map1"> $imageMap </map> <br> <!----------------------------------------------------- Create the DIV layers to show detail information --------------------------------------------------------> EndOfHTML ; for($i = 0; $i < scalar(@$revenue); ++$i) { print <<EndOfHTML <div id="info$i" style="visibility:hidden;position:absolute;left:65px;"> <b>Year $labels->[$i]</b><br> Revenue : USD $revenue->[$i]K<br> Gross Margin : $grossMargin->[$i]%<br> Back Log : USD $backLog->[$i]K<br> A/C Receviable : USD $receviable->[$i]K<br> </div> EndOfHTML ; } print <<EndOfHTML <!----------------------------------------------------- Client side utility function to show and hide a layer. Works in both IE and Netscape browsers. --------------------------------------------------------> <SCRIPT> function setDIV(id, cmd) { if (document.getElementById) //IE 5.x or NS 6.x or above document.getElementById(id).style.visibility = cmd; else if (document.all) //IE 4.x document.all[id].style.visibility = cmd; else //Netscape 4.x document[id].visibility = cmd; } </SCRIPT> </body> </html> EndOfHTML ;

In the above code, the chart is created and saved in a temporary file using BaseChart.makeTmpFile. An <IMG> tag is used to retrieve the chart with "myimage.pl?img=/tmp/tmpcharts/$chart1URL" as the URL. "myimage.pl" is a simple utility that comes with ChartDirector for retrieving images from files.

The image map for the chart is created using the following code:

#Client side Javascript to show detail information "onmouseover" my $showText = "onmouseover='setDIV(\"info{x}\", \"visible\");' "; #Client side Javascript to hide detail information "onmouseout" my $hideText = "onmouseout='setDIV(\"info{x}\", \"hidden\");' "; #"title" attribute to show tool tip my $toolTip = "title='{xLabel}: USD {value|0}K'"; #Create an image map for the chart my $imageMap = $c->getHTMLImageMap("xystub.pl", "", "$showText$hideText$toolTip" );

Note that in additional to the "title" attribute for the "tool tip", the image map also includes "onmouseover" and "onmouseout" attributes. These two attributes will instruct the browser to execute the corresponding code when the mouse moves over and moves out of the areas defined in the <area> tags.

The code in the "onmouseover" and "onmouseout" attribute calls a client side Javascript function "setDIV". This function is simple a utility to show and hide a DIV block in dynamic HTML. The definition of "setDIV" is as follows. It is included as part of the web page to be sent to the browser.

<!----------------------------------------------------- Client side utility function to show and hide a layer. Works in both IE and Netscape browsers. --------------------------------------------------------> <SCRIPT> function setDIV(id, cmd) { if (document.getElementById) //IE 5.x or NS 6.x or above document.getElementById(id).style.visibility = cmd; else if (document.all) //IE 4.x document.all[id].style.visibility = cmd; else //Netscape 4.x document[id].visibility = cmd; } </SCRIPT>

The DIV blocks that show the detail information are generated using the following code.

<!----------------------------------------------------- Create the DIV layers to show detail information --------------------------------------------------------> for($i = 0; $i < scalar(@$revenue); ++$i) { print <<EndOfHTML <div id="info$i" style="visibility:hidden;position:absolute;left:65px;"> <b>Year $labels->[$i]</b><br> Revenue : USD $revenue->[$i]K<br> Gross Margin : $grossMargin->[$i]%<br> Back Log : USD $backLog->[$i]K<br> A/C Receviable : USD $receviable->[$i]K<br> </div> EndOfHTML ;

Each data point is associated with a DIV block that shows its detail information. As seen from the "style" attribute in the above code, initially the DIV blocks are hidden. When the mouse moves over the area defined in an <area> tag, the "onmouseover" event handler will call the "setDIV" function to show the coresponding DIV block. When the mouse moves out of that area, the "onmouseout" event handler will call the "setDIV" function to hide the DIV block.

In addition to responding to mouse over and mouse out events, the area chart is also clickable using "xystub.pl" as the handler. For demo purpose, "xystub.pl" simply displays what is clicked.

[The following is available as "perldemo_cgi/xystub.pl".]
#!/usr/bin/perl #standard code to parse HTTP query parameters my %query = map {my($k,$v) = split(/=/)} split(/&/, $ENV{"QUERY_STRING"}); print "Content-type: text/html\n\n"; print <<EndOfHTML <html> <body> <h1>Simple Clickable XY Chart Handler</h1> <p><a href="viewsource.pl?file=$ENV{"SCRIPT_NAME"}"> View Source Code </a></p> <p><b>You have clicked on the following chart element :</b></p> <ul> <li>Data Set : $query{"dataSetName"}</li> <li>X Position : $query{"x"}</li> <li>X Label : $query{"xLabel"}</li> <li>Data Value : $query{"value"}</li> </ul> </body> </html> EndOfHTML ;