Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: HTML::Template, pseudo trees and indention.

by dragonchild (Archbishop)
on Jan 10, 2006 at 14:19 UTC ( [id://522179]=note: print w/replies, xml ) Need Help??


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:
  1. Does it work?
  2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
  • Comment on Re: HTML::Template, pseudo trees and indention.

Replies are listed 'Best First'.
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)
      • c1 (depth=2)
        • c1.1 (depth=3)
    • 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

/\/\averick

      *claps sardonically* I was waiting for that response. You did it with H::T, not within H::T. Your node is an excellent example of twisting the problem to suit the answer. Not only is your template nearly unreadable the first 3 times one reads it, but your code is nearly impossible to follow as well. The point wasn't to see if you could code a solution that involves H::T. The point was to see if H::T could provide a solution.

      And, yes, any recursive solution can be written iteratively. That doesn't mean that H::T can handle it any better.


      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
        /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 :)

        /\/\averick

      Here is a bit simpler version. I'm not sure this doesn't miss some special case you where planning on though. It just makes an up or a down loop to raise or level the level as needed.

      #!/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;


      ___________
      Eric Hodges
        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".

        /\/\averick

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.
      Getting Tree::Persist::DB to work with your schema should be relatively easy. Good luck!

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://522179]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (9)
As of 2024-04-23 11:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found