in reply to HTML::Template, pseudo trees and indention.
You can't do it within HTML::Template, period. You can do it within Template Toolkit simply because TT allows you to create recursive functions which are the easiest way to handle recursive data structures, such as trees.
Furthermore, is there a reason you're using a flat array vs. one of the CPAN solutions like Tree or Tree::Simple? Tree::Simple provides for a huge number of visitors, some of which handle layout in terms of spaces. Tree has an persistence mode that writes to an XML file that you can use XSL to transform into HTML. Heck, it would be extremely simple to write a "persistence" layer for Tree that persists to HTML vs. XML and writes to an IO::Scalar object vs. a filehandle.
My criteria for good software:
- Does it work?
- Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re^2: HTML::Template, pseudo trees and indention.
by maverick (Curate) on Jan 10, 2006 at 15:42 UTC
|
quote: You can't do it within HTML::Template, period
According to whom?
#!/usr/bin/perl
use strict;
use HTML::Template;
my $template = "
<ul>
<TMPL_LOOP tree>
<li><TMPL_VAR value> (depth=<TMPL_VAR depth>)
<TMPL_LOOP open><ul></TMPL_LOOP>
<TMPL_IF close>
<TMPL_LOOP close>
</li></ul>
<TMPL_IF __LAST__></li></TMPL_
+IF>
</TMPL_LOOP>
<TMPL_ELSE>
<TMPL_UNLESS open>
</li>
</TMPL_UNLESS>
</TMPL_IF>
</TMPL_LOOP>
</ul>
";
my $tree = [
{ 'value' => 'a', 'depth' => 1 },
{ 'value' => 'b', 'depth' => 1 },
{ 'value' => 'b1', 'depth' => 2 },
{ 'value' => 'b2', 'depth' => 2 },
{ 'value' => 'c', 'depth' => 1 },
{ 'value' => 'c1', 'depth' => 2 },
{ 'value' => 'c1.1', 'depth' => 3 },
{ 'value' => 'd', 'depth' => 1 }
];
for my $i (0 .. $#$tree) {
my $delta;
if (defined($tree->[$i+1])) {
$delta = $tree->[$i+1]->{'depth'} - $tree->[$i]->{'dep
+th'};
}
else {
$delta = - $tree->[$i]->{'depth'};
}
if ($delta > 0) {
push(@{$tree->[$i]->{'open'}},{}) for (1 .. $delta);
}
elsif ($delta < 0) {
push(@{$tree->[$i]->{'close'}},{}) for ($delta .. -1);
}
}
my $html_template = HTML::Template->new(
scalarref => \$template,
loop_context_vars => 1);
$html_template->param('tree' => $tree);
print $html_template->output;
Produces the following html:
- a (depth=1)
- b (depth=1)
- b1 (depth=2)
- b2 (depth=2)
- c (depth=1)
- d (depth=1)
Isn't there some law of comp-sci that says that say any algorithm that can be written recusively, can also be written iteratively? er...or something to that effect.
Update: fixted sprelling erors
| [reply] [d/l] |
|
| [reply] |
|
/me reads question again.
...only for strict definitions of "twist". He already has the tree as an array. He already has the depth of the nodes in the tree. The only thing he's missing is the not-so-magical trick of having H::T produce html to create the changes in depth. For that you need to know how much and which way the depth changes between any two nodes and then use a tmpl_loop to generate the right number of opens / closes.
Granted the code needs comments, but impossible to follow is a stretch. jeffa figured it out sans comments in the time it took me to type this respone...can't be that bad :)
| [reply] |
|
|
|
#!/usr/bin/perl
use strict;
use HTML::Template;
use Data::Dumper;
my $template = "
<ul>
<TMPL_LOOP tree>
<li><TMPL_VAR value> (depth=<TMPL_VAR depth>)
<TMPL_LOOP up><ul></TMPL_LOOP>
<TMPL_LOOP down></ul></TMPL_LOOP>
</li>
</TMPL_LOOP>
</ul>
";
my $tree = [
{ 'value' => 'a', 'depth' => 1 },
{ 'value' => 'b', 'depth' => 1 },
{ 'value' => 'b1', 'depth' => 2 },
{ 'value' => 'b2', 'depth' => 2 },
{ 'value' => 'c', 'depth' => 1 },
{ 'value' => 'c1', 'depth' => 2 },
{ 'value' => 'c1.1', 'depth' => 3 },
{ 'value' => 'd', 'depth' => 1 }
];
for my $i (0 .. $#$tree) {
if (defined $tree->[$i+1]) {
my $diff = $tree->[$i+1]->{depth} - $tree->[$i]->{depth};
if ($diff > 0) {
$tree->[$i]->{up} = [({}) x $diff];
} elsif ( $diff < 0 ) {
$tree->[$i]->{down} = [({}) x -$diff];
}
}
}
my $html_template = HTML::Template->new(
scalarref => \$template,
loop_context_vars => 1);
$html_template->param('tree' => $tree);
print $html_template->output;
| [reply] [d/l] |
|
On first glance, the subtle difference is that mine generates all the "optional" closing "li"s. I'm actually using this to generate collapsable trees in a web based app and some of the more drain bamaged *cough* IE *cough* browsers yacked if the html wasn't "well formed".
| [reply] |
|
Re^2: HTML::Template, pseudo trees and indention.
by BUU (Prior) on Jan 10, 2006 at 21:00 UTC
|
Heh, the reason I'm using a flat array is because that's how it comes out of the database =]. I was attempting to be as lazy as possible and just pass the data to my template, but I have to admit the contortions involved are really fairly ugly (Sorry guys). I'm now leaning strongly towards one of the Tree modules, thanks. | [reply] |
|
Getting Tree::Persist::DB to work with your schema should be relatively easy. Good luck!
My criteria for good software:
- Does it work?
- Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
| [reply] |
|
|