Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
Below is a module I've written to dynamically create HTML tables. I've never liked creating them by hand. Comments and suggestions are very welcome.
package CGI::Tables; use strict; use vars qw[@ISA @EXPORT $VERSION]; $VERSION = '0.9'; require Exporter; @ISA = qw(Exporter); @EXPORT = qw(table); #feedit: options, data #receive: html #effect: none sub table { my $data = pop; my $keyed = { @_ }; my $html; my %attrs = %{shift @$data} if "HASH" eq ref $data->[0]; $data = arrange($data, $keyed) if $keyed->{cols} or $keyed->{rows}; $data = add_titles($keyed, $data) if $keyed->{col_titles} or $keyed->{row_titles}; $html .= "<table" . attributes(%attrs) . ">\n"; $html .= row(@$_) for @$data; $html .= "</table>\n"; return $html; } #feedit: row data #receive: html #effect: none sub row { my (@cells) = @_; my %attrs = %{shift @cells} if "HASH" eq ref $cells[0]; my $html = "<tr" . attributes(%attrs) . ">"; $html .= cell($_) for @cells; $html .= "</tr>\n"; return $html; } #feedit: cell data #receive: html #effect: none sub cell { my ($data) = @_; return "<td>$data</td>" if not ref $data; my %attrs = %{shift @$data} if "HASH" eq ref $data->[0]; my $html = "<td" . attributes(%attrs) . ">"; $html .= $_ for @$data; $html .= "</td>"; $html =~ s/td/th/g if $attrs{_header}; return $html; } #feedit: keyed args, data #receive: data #effect: none sub add_titles { my ($keyed, $data) = @_; my @titled; if ($keyed->{col_titles}) { my @titles; push @titles, title($keyed->{col_titles}, $_) for 0..$#{$data->[0]}; push @titled, [@titles]; } if ($keyed->{row_titles}) { unshift @{$titled[0]}, "" if $keyed->{col_titles}; for (0..$#$data) { push @titled, [ title($keyed->{row_titles}, $_), @{$data->[$_]} ]; } } else { push @titled, @$data; } return \@titled; } #feedit: titles, col/row number #receive: title #effect: none sub title { my ($titles, $n) = @_; my $title; if ("ARRAY" eq ref $titles) { $title = $titles->[$n]; } elsif ("CODE" eq ref $titles) { $title = $titles->($n); } return [ {_header=>1}, $title ]; } #feedit: attribute hash #receive: code for inside html tags #effect: none sub attributes { my (%attrs) = @_; my $html = ""; for (keys %attrs) { next if $_ =~ /^_/; $html .= " $_=\"$attrs{$_}\""; } return $html; } #feedit: data, keyed #receive: arranged data #effect: none sub arrange { my ($data, $keyed) = @_; my ($rows, $cols) = size($#$data + 1, $keyed); # add extra cells that are needed push @$data, "" until $#$data + 1 == $rows * $cols; my @arranged; if ($keyed->{cols}) { for (1..$rows) { push @arranged, [ splice @$data, 0, $cols ]; } } else { push @arranged, [] for 1..$rows; while (@$data) { push @$_, shift @$data for @arranged; } } return \@arranged; } #feedit: number of data elements, keyed #receive: number of rows, cols #effect: none sub size { my ($n_data, $keyed) = @_; my ($rows, $cols, $ratio); if ($rows = $keyed->{rows}) { $cols = divisor($n_data, $rows); } elsif ($cols = $keyed->{cols}) { $rows = divisor($n_data, $cols); } return $rows, $cols; } #feedit: number of data elements, number of (rows, cols) #receive: number of other way #effect: none sub divisor { my ($n_data, $rows) = @_; my $cols = int $n_data / $rows; $cols++ if $n_data % $rows; return $cols; } 1; __END__ =head1 NAME CGI::Tables - An easy way to create HTML tables =head1 SYNOPSIS use CGI::Tables; print table cols => 2, [qw(Cell Cell Cell)]; =head1 DESCRIPTION Only one function is exported: C<table()>. You pass it the parameters +and the data, in that order. The data is passed as an array ref and the parameters as a list. In return, you get HTML for a table. =head2 Arranging Data There are three ways to set up the data. All of the examples in this section produce identical tables. =over =item Hard Coding This method is the old fashioned way. If you're lazy (it's a virtue), +use one of the other two. This I<is> the most efficient way though. Pass t +he rows as array refs and the cells inside that. table [ [ "Row 1 Cell 1", "Row 1 Cell 2", "Row 1 Cell 3" ], [ "Row 2 Cell 1", "Row 2 Cell 2", "Row 2 Cell 3" ] ]; =item Cols If you pass the number of columns you want and put the cells in the da +ta array ref, CGI::Tables will automagically figure out how many rows the +re are and place the data in the correct place. The cells go from left to + right, top to bottom. table cols => 3, [ "Row 1 Cell 1", "Row 1 Cell 2", "Row 1 Cell 3", "Row 2 Cell 1", "Row 2 Cell 2", "Row 2 Cell 3" ]; =item Rows This is similar to passing the number of columns. The only difference is that the data as arranged top to bottom, left to right. table rows => 2, [ "Row 1 Cell 1", "Row 2 Cell 1", "Row 1 Cell 2", "Row 2 Cell 2", "Row 1 Cell 3", "Row 2 Cell 3" ]; =back =head2 Cells When passing a cell, it is perfectly acceptable to pass a string. You +can pass an array ref if you so desire. The elements of ref will be concatenate +d and placed in the cell. =head2 Column and Row Headers Column and row headers are passed by C<col_titles> and C<row_titles>, respectively. You can either pass an array ref of titles or a code/sub +routine reference. Code refs are passed column/row indices, which start at zer +o. Examples: table rows => 2, col_titles => sub { return "Col " . (shift() + 1) } +, [ @data ]; table rows => 2, row_titles => ["Row 1", "Row 2"], [ @data ]; =head2 Specifying HTML Attributes HTML attributes can be specifed for the table, a row, or a cell. Stick + a hash ref as the first element in the appropriate array ref, and it wil +l be added. For cells, pass an array ref (which would otherwise be optional +) with a hash ref in front. Row attributes cannot be passed when the tab +le is created dynamically. The following example will print a table of width + 600 with one cell that has #660000 as the background color. table cols => 2, [ {width => 600}, [ {bgcolor => "#660000"}, "Cell 1 +" ], "Cell 2", "Cell 3", "Cell 4" ]; =head1 AUTHOR Matthew Diephouse matt@diephouse.com =cut

elusion : http://matt.diephouse.com


In reply to RFC: CGI::Tables by elusion

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others surveying the Monastery: (6)
    As of 2015-07-04 16:13 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









      Results (60 votes), past polls