jrsimmon has asked for the wisdom of the Perl Monks concerning the following question:

Using CGI, DBI, and GD::Graph, I am creating a basic reporting application. I would like the charts in this application to have image maps which will enable the user to drill down on any given data point of any given chart.

A good drill down has two parts.
First, rollover should be enabled so the user can see the values that are represented by a given data point.
Second, the user should be able to click on a given data point, generating a new chart that is more narrowly focused on his/her selection.
GD::Graph::Map appears to be the perfect solution for this. So far, though, I have not been able to get the data point links (hrefs option of the GD::Graph::Maps object) or the rollover information (info options of the same object) to work. Whenever I generate a chart, the data points are hyperlinked, but the link itself is the default link for the GD::Graph::Maps object, which is "javascript:;". The rollover values also do not get substituted (%x should be substituted by the x-axis value, %y substituted by the y-axis value -- i actually get %x,%y). Here's my script in its entirety:
#!C:\perl\bin\perl.exe use strict; use warnings; use CGI ':standard'; use GD::Graph::lines; use GD::Graph::Map; use DBI; use Data::Dumper; my $db = "..."; my $user = "..."; my $pwd = "..."; my $dbh = DBI->connect("DBI:DB2:$db", "$user", "$pwd", {RaiseError => +0, AutoCommit => 1}); my $stmt = "..."; my $sth = $dbh->prepare($stmt); my $rc = $sth->execute; my $data = $sth->fetchall_arrayref; $sth->finish; my @dates = (); my @values = (); my @urls = (); my $baseURL = "http://localhost:8080/cgi-bin/index.cgi?date="; foreach my $entry (@$data){ push(@dates, $entry->[0]); push(@values, $entry->[1]); push(@urls, $baseURL . $entry->[0]); } my @chartData = ([@dates], [@values]); my $graph = GD::Graph::lines->new(1300, 600); $graph->set( x_label => 'Date', y_label => 'Transaction Count', title => 'Transaction Counts by Day', y_max_value => 2500, y_min_value => 0, y_tick_number => 10, y_label_skip => 2, box_axis => undef, line_width => 2, ); open(CHART, ">../htdocs/chart.png") or die; binmode CHART; print CHART $graph->plot(\@chartData)->png; close(CHART); my $map = new GD::Graph::Map($graph, hrefs=>\@urls, noImgMarkup=>0, mapName=>"chartmap", info=>'%x,%y', ); print header, start_html('Simple Script'), h1('Simple Script'), hr, img({src=>"/chart.png", usemap=>"#chartmap"}), ($map->imagemap("chart.png", \@chartData)); print end_html; print Dumper @dates; print Dumper @values; print Dumper @urls;

If run from the command line, it produces the following output:
<title>Simple Script</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1 +" /> </head> <body> <h1>Simple Script</h1><hr /><img usemap="#chartmap" src="/chart.png" / +><Map Name=chartmap> <Area Shape=polygon Coords="82, 433, 122, 326, 163, 383, 203, 370, + 244, 344, 284, 443, 325, 457, 366, 424, 406, 422, 447, 329, 487, 376 +, 528, 322, 569, 310, 609, 364, 650, 338, 690, 322, 731, 346, 771, 35 +8, 812, 408, 853, 442, 893, 451, 934, 421, 974, 284, 1015, 356, 1056, + 374, 1096, 408, 1137, 416, 1177, 465, 1218, 440, 1258, 381, 1258, 38 +5, 1218, 444, 1177, 469, 1137, 420, 1096, 412, 1056, 378, 1015, 360, +974, 288, 934, 425, 893, 455, 853, 446, 812, 412, 771, 362, 731, 350, + 690, 326, 650, 342, 609, 368, 569, 314, 528, 326, 487, 380, 447, 333 +, 406, 426, 366, 428, 325, 461, 284, 447, 244, 348, 203, 374, 163, 38 +7, 122, 330, 82, 437" Href="javascript:;" Title="%x,%y" Alt="%x,%y" o +nMouseOver="window.status='%x,%y'; return true;" onMouseOut="window.s +tatus=''; return true;"> </Map> </body> </html>$VAR1 = '2009-06-01'; $VAR2 = '2009-06-02'; $VAR3 = '2009-06-03'; $VAR4 = '2009-06-04'; $VAR5 = '2009-06-05'; $VAR6 = '2009-06-06'; $VAR7 = '2009-06-07'; $VAR8 = '2009-06-08'; $VAR9 = '2009-06-09'; $VAR10 = '2009-06-10'; $VAR11 = '2009-06-11'; $VAR12 = '2009-06-12'; $VAR13 = '2009-06-13'; $VAR14 = '2009-06-14'; $VAR15 = '2009-06-15'; $VAR16 = '2009-06-16'; $VAR17 = '2009-06-17'; $VAR18 = '2009-06-18'; $VAR19 = '2009-06-19'; $VAR20 = '2009-06-20'; $VAR21 = '2009-06-21'; $VAR22 = '2009-06-22'; $VAR23 = '2009-06-23'; $VAR24 = '2009-06-24'; $VAR25 = '2009-06-25'; $VAR26 = '2009-06-26'; $VAR27 = '2009-06-27'; $VAR28 = '2009-06-28'; $VAR29 = '2009-06-29'; $VAR30 = '2009-06-30'; $VAR1 = '612'; $VAR2 = '1099'; $VAR3 = '842'; $VAR4 = '899'; $VAR5 = '1016'; $VAR6 = '567'; $VAR7 = '504'; $VAR8 = '654'; $VAR9 = '665'; $VAR10 = '1085'; $VAR11 = '871'; $VAR12 = '1120'; $VAR13 = '1174'; $VAR14 = '929'; $VAR15 = '1047'; $VAR16 = '1118'; $VAR17 = '1008'; $VAR18 = '954'; $VAR19 = '729'; $VAR20 = '574'; $VAR21 = '534'; $VAR22 = '668'; $VAR23 = '1292'; $VAR24 = '965'; $VAR25 = '880'; $VAR26 = '727'; $VAR27 = '689'; $VAR28 = '470'; $VAR29 = '582'; $VAR30 = '852'; $VAR1 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-01'; $VAR2 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-02'; $VAR3 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-03'; $VAR4 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-04'; $VAR5 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-05'; $VAR6 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-06'; $VAR7 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-07'; $VAR8 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-08'; $VAR9 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-09'; $VAR10 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-10'; $VAR11 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-11'; $VAR12 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-12'; $VAR13 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-13'; $VAR14 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-14'; $VAR15 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-15'; $VAR16 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-16'; $VAR17 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-17'; $VAR18 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-18'; $VAR19 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-19'; $VAR20 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-20'; $VAR21 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-21'; $VAR22 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-22'; $VAR23 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-23'; $VAR24 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-24'; $VAR25 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-25'; $VAR26 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-26'; $VAR27 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-27'; $VAR28 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-28'; $VAR29 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-29'; $VAR30 = 'http://localhost:8080/cgi-bin/index.cgi?date=2009-06-30';
The webpage itself looks fine, just no datapoint rollover info or hyperlinks. I see where that data is wrong in the Area tag, I just don't understand what I should be doing for it to be set correctly.

Update:
I should point out this is a browser-based reporting app.
Update2:
When I switch from a line chart to a pie chart, the hrefs and rollovers work. Is that functionality broken with the line charts?

Replies are listed 'Best First'.
Re: Problem with GD::Graph::Map hrefs and info options
by jrsimmon (Hermit) on Jul 07, 2009 at 22:07 UTC
    It seems that GD::Graph::Map is inconsistent between graph types. In order to add links to data points for a line graph, you must pass the url list to the lhref option of the map object instead of the (documented) href option. For the pie chart, the href option is used. The linepoints graphs do not appear to work at all.

    I'm still trying to track down the rollover problem. Suggestions are much appreciated.

    Update:
    This turns out not to work. lhrefs sets each href to the value of the first x-axis label. So there's a valid link, but it's essentially useless. Boo incomplete cpan modules that aren't documented as such.