Re: HTML::Template, pseudo trees and indention.
by BrowserUk (Patriarch) on Jan 10, 2006 at 09:58 UTC
|
This is one of those occasions when the markup & presentation logic is intimately intertwined with the content no matter how hard you try to separate them.
Rather than trying to put complex logic within the template and it's highly restrictive mini-language, better to simply produce the html representing the tree as a string, using the full power of Perl, and the pass it into the template for incorporation with the rest of the page elements.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |
Re: HTML::Template, pseudo trees and indention.
by dragonchild (Archbishop) on Jan 10, 2006 at 14:19 UTC
|
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?
| [reply] |
|
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] |
|
|
|
|
#!/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] |
|
|
|
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] |
Re: HTML::Template, pseudo trees and indention.
by talexb (Chancellor) on Jan 10, 2006 at 09:19 UTC
|
Can you do recursive includes using HTML::Template? That would do it, I think.
Alex / talexb / Toronto
"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds
| [reply] |
Re: HTML::Template, pseudo trees and indention.
by dws (Chancellor) on Jan 10, 2006 at 15:02 UTC
|
I confess I've got no ideas that don't involve ugly hacks to my data and the template (such as storing a special variable in the array every time it changes level.
Don't think of it as an ugly hack. Think of it as one of life's many trade-offs. You're doing some set-up in code so that you don't have to contort your template.
If the depth of the tree you're dealing with can't be bounded, you can generate indentations in code, and do something like
<tmpl_loop tree>
<div class="leaf" style="margin-left: <tmpl_var margin>px"> ... </di
+v>
This has the upside of giving you fine-grain control over indentation, with the downside of that control being in code rather than in your template.
If the depth of the tree is bounded, you can move presentation into the stylesheet by generating a simple depth count in code. In the template, do something like
<tmpl_loop tree>
<div class="leaf depth<tmpl_var depth>"> ... </div>
and provide corresponding depth0, depth1, etc. targets in your stylesheet, with the generic style in leaf.
| [reply] [d/l] [select] |