You have several lists and tables to generate and would like helper functions to make these easier to output.
The CGI module provides HTML helper functions which, when passed array references, apply themselves to each element of the referenced array:
print ol( li([ qw(red blue green)]) );@names = qw(Larry Moe Curly); print ul( li({ -TYPE => "disc" }, \@names) );
<OL><LI>red</LI> <LI>blue</LI> <LI>green</LI></OL>
<UL><LI TYPE="disc">Larry</LI> <LI TYPE="disc">Moe</LI>
<LI TYPE="disc">Curly</LI></UL>
The distributive behavior of the HTML generating functions in CGI.pm can significantly simplify generation of lists and tables. Passed a simple string, they just produce HTML for that string. But passed an array reference, they work on all those strings.
print li("alpha");print li( [ "alpha", "omega"] );
<LI>alpha</LI>
<LI>alpha</LI> <LI>omega</LI>
The shortcut functions for lists will be loaded when you use the :standard
import tag, but you need to ask for :html3
explicitly to get helper functions for working with tables. There's also a conflict between the <TR>
tag, which would normally make a tr()
function, and Perl's built-in tr///
operator. Therefore, to make a table row, use the Tr()
function.
This example generates an HTML table starting with a hash of arrays. The keys will be the row headers, and the array of values will be the columns.
use CGI qw(:standard :html3); %hash = ( "Wisconsin" => [ "Superior", "Lake Geneva", "Madison" ], "Colorado" => [ "Denver", "Fort Collins", "Boulder" ], "Texas" => [ "Plano", "Austin", "Fort Stockton" ], "California" => [ "Sebastopol", "Santa Rosa", "Berkeley" ], ); $\ = "\n"; print "<TABLE> <CAPTION>Cities I Have Known</CAPTION>"; print Tr(th [qw(State Cities)]); for $k (sort keys %hash) { print Tr(th($k), td( [ sort @{$hash{$k}} ] )); } print "</TABLE>";
That generates text that looks like this:
<TABLE> <CAPTION>Cities I Have Known</CAPTION>
<TR><TH>State</TH> <TH>Cities</TH></TR>
<TR><TH>California</TH> <TD>Berkeley</TD> <TD>Santa Rosa</TD>
<TD>Sebastopol</TD> </TR>
<TR><TH>Colorado</TH> <TD>Boulder</TD> <TD>Denver</TD>
<TD>Fort Collins</TD> </TR>
<TR><TH>Texas</TH> <TD>Austin</TD> <TD>Fort Stockton</TD>
<TD>Plano</TD></TR>
<TR><TH>Wisconsin</TH> <TD>Lake Geneva</TD> <TD>Madison</TD>
<TD>Superior</TD></TR>
</TABLE>
You can produce the same output using one print statement, although it is slightly trickier, because you have to use a map
to create the implicit loop. This print statement produces output identical to that displayed above:
print table caption('Cities I have Known'), Tr(th [qw(State Cities)]), map { Tr(th($_), td( [ sort @{$hash{$_}} ] )) } sort keys %hash;
This is particularly useful for formatting the results of a database query, as in Example 19.3 (see Chapter 14, Database Access).
#!/usr/bin/perl # salcheck - check for salaries use DBI; use CGI qw(:standard :html3); $limit = param("LIMIT"); print header(), start_html("Salary Query"), h1("Search"),start_form()
, p("Enter minimum salary", textfield("LIMIT")),submit(),
end_form();
if (defined $limit) { $dbh = DBI->connect("dbi:mysql:somedb:server.host.dom:3306", "username", "password") or die "Connecting: $DBI::errstr"; $sth = $dbh->prepare("SELECT name,salary FROM employees WHERE salary > $limit") or die "Preparing: ", $dbh->errstr; $sth->execute or die "Executing: ", $sth->errstr; print h1("Results"), "<TABLE BORDER=1>"; while (@row = $sth->fetchrow_array())
{ print Tr( td( \@row ) ); } print "</TABLE>\n"; $sth->finish; $dbh->disconnect; } printend_html();
The documentation for the standard CGI module; Recipe 14.10