in reply to Readable HTML tables
I agree that maps, and nested maps in particular, are less readable than normal loops. Your code is very readable. But I like pure functions. This approach leaves me no easy way to stick the generated HTML into a variable. And it may just be that it is 3 AM hereabouts, but I cannot see how to do nested tables at all, when the table function is written to print.
So, here is an alternative, returning good old-fashioned strings. Beware, I have been known to overdesign stuff. In fact, I am getting dangerously close to inventing a HTML templating system, aren't I? :-)
But the code actually using the functions should still be readable, I hope.
Update: My original implementation of these routines had a memory leak. Also, the functions' behaviour when called in non-void context "inside" another call ... did not DWIM. While the first problem could be solved in several ways, the least bad solution I found to the second, was to make the functions' behaviour depend on void context or not.
Having made this change, the original three examples remain unchanged, and produce the same output as before. My two new examples illustrate the second problem.
{ my %coll; $coll{contents} = \0; # A ref. Any ref. my $element = sub { my ($name, $optional_newline) = @_;; $optional_newline ||= ''; return sub (&) { my $ret = do { # I cannot localize lexicals, but I can localize members of a # lexically scoped aggregate, much to the same effect: local $coll{contents}=""; local $coll{attributes}=""; shift->(); "<$name$coll{attributes}>$optional_newline" . "$coll{contents}</$name>$optional_newline"; }; if (defined wantarray) { return $ret; } elsif (ref $coll{contents}) { return; } else { $coll{contents} .= $ret; return; # We are in void context, but might as well be explici +t. } }; }; sub table (&); sub row (&); sub cell (&); *table = $element->( table => $/ ); *row = $element->( 'tr' => $/ ); *cell = $element->( 'td' ); # The only way to get any actual contents: sub lit (@) { $coll{contents} .= $_ for @_ } # In the simple case, this one reads a lot better: sub cells (@) { cell { lit $_; } for @_ } # I cannot approach a templating system without attributes, right? # (I am sorry already. I just cannot help it ...) sub att (@) { # Sets/unsets all attributes each time -- last call gets served: $coll{attributes}=""; while (@_) { my ($key, $value) = (shift, shift); unless (defined $value) { $coll{attributes} .= " $key"; next; } # From CGI::Utils::simple_escape: $value =~ s{&}{&}gso; $value =~ s{<}{<}gso; $value =~ s{>}{>}gso; $value =~ s{\"}{"}gso; $coll{attributes} .= qq( $key="$value"); } } } # Your examples would then need s/cell/cells/g and a print: print table { for (1..10) { row { cells "foo", "bar", "baz"; } } }; print table { row { cells @$_ } for $db->query('SELECT * FROM foo')->a +rrays }; # I have been known to overdesign my examples as well ... print table { att border => 1; my %valign = qw( foo top bar center baz bottom); my $quux_cell = sub { my $quux = shift; cell { lit $quux; att valign => $valign{$quux} if $valign{$quux}; +}; }; for (1..10) { row { cell { table { for ("top", "center", "bottom") { row { cell { att align => 'center'; lit $_; }; }; } }; }; for (qw/foo bar baz/) { $quux_cell->($_); } } } }; # New examples, per the update (see above): # Would have had the rows appearing twice in my original implementatio +n; # the first time in the order generated: print table { my @r = map {row { cells $_, $_*$_ }} 1..10; for (0..$#r) { my $j = rand($_); @r[$_,$j]=@r[$j,$_]; } lit @r; }; # Would have had all of the inner tables appearing twice in my # original implementation; the first time at the start of the row, # outside of the TD elements: print table { my $x; for (1..3) { row { for (1..3) { ++$x; cells $x, table { att border => 1; for (1..$x) { row { cells((" ")x$x) } } }; } }; } };
The Sidhekin
print "Just another Perl ${\(trickster and hacker)},"
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Re: Readable HTML tables
by Juerd (Abbot) on Aug 26, 2003 at 05:29 UTC | |
by Sidhekin (Priest) on Aug 26, 2003 at 08:14 UTC | |
by Juerd (Abbot) on Aug 26, 2003 at 09:49 UTC |