in reply to Nested loops in HTML::Template

Wrapping your template in a bit of Perl code for better understanding, I get the following:
use strict; use HTML::Template; # use File::Find; # use File::Find's wanted() method to gather # all directories/files... my $dir_list = [ { dir => 'foo', dir_row => [ { file_row => [ { filename +=> 'foo0.pic' }, { filename +=> 'foo1.pic' }, { filename +=> 'foo2.pic' }, { filename +=> 'foo3.pic' }, { filename +=> 'foo4.pic' } ] # for fil +e_row } ] # for dir_row }, { dir => 'bar', dir_row => [ { file_row => [ { filename +=> 'bar0.pic' }, { filename +=> 'bar1.pic' }, { filename +=> 'bar2.pic' }, { filename +=> 'bar3.pic' }, { filename +=> 'bar4.pic' } ] # for fil +e_row } ] # for dir_row } ]; my $tmpl = new HTML::Template(type => 'filehandle', source => *DATA); $tmpl->param(dir_list => $dir_list); print $tmpl->output(); print "here\n"; __DATA__ <html> <head> <title><TMPL_VAR NAME="title"></title> </head> <body> <center> <table> <TMPL_LOOP NAME="dir_list"> <tr> <th colspan="5" bgcolor="#E0E0E0"><font size="+3"> <TMPL_VAR NAME="dir"></font></th> </tr> <TMPL_LOOP NAME="dir_row"> <tr> <TMPL_LOOP NAME="file_row"> <td colspan="5"><TMPL_VAR NAME="filename"></td> </TMPL_LOOP> </tr> </TMPL_LOOP> </TMPL_LOOP> </table> </center> </body> </html>
I didn't test the code yet, but think that it's somewhat close to what you'd want your data structure to look like. Also, I had to change the names you chose for your loops to make things a bit more clear ;-). See, it is already obvious that 'outter_file_loop' is infact an 'outer' loop since it is outside of the 'inner' loop. What is not obvious, however, is what kind of data that loop is 'cycling' through. So, by naming that as 'dir row' I know that the outer loop is in fact cycling through directories whereas the 'inner' loop (which I named 'file_row') cycles through list of files (5 files) in that directory.

UPDATE: Fixed data structure a bit and tested the script.. The output I get is
<html> <head> <title></title> </head> <body> <center> <table> <tr> <th colspan="5" bgcolor="#E0E0E0"><font size="+3"> foo</font></th> </tr> <tr> <td colspan="5">foo0.pic</td> <td colspan="5">foo1.pic</td> <td colspan="5">foo2.pic</td> <td colspan="5">foo3.pic</td> <td colspan="5">foo4.pic</td> </tr> <tr> <th colspan="5" bgcolor="#E0E0E0"><font size="+3"> bar</font></th> </tr> <tr> <td colspan="5">bar0.pic</td> <td colspan="5">bar1.pic</td> <td colspan="5">bar2.pic</td> <td colspan="5">bar3.pic</td> <td colspan="5">bar4.pic</td> </tr> </table> </center> </body> </html>


UPDATE: Should you need any help filling the actual data structure using 'File::Find' module or some such, let me know.

UPDATE 1: If you were looking at more than 5 files in a given directory, the structure you may expect to get will look something like this:
my $dir_list = [ { dir => 'foo', dir_row => [ { file_row => [ { filename +=> 'foo0.pic' }, { filename +=> 'foo1.pic' }, { filename +=> 'foo2.pic' }, { filename +=> 'foo3.pic' }, { filename +=> 'foo4.pic' } ] }, # for fi +le_row # second row (next batch o +f files of 5) { file_row => [ { filename +=> 'foo5.pic' }, { filename +=> 'foo6.pic' }, { filename +=> 'foo7.pic' }, { filename +=> 'foo8.pic' }, { filename +=> 'foo9.pic' } ] }, # for fi +le_row ] # for dir_row }, { dir => 'bar', dir_row => [ { file_row => [ { filename +=> 'bar0.pic' }, { filename +=> 'bar1.pic' }, { filename +=> 'bar2.pic' }, { filename +=> 'bar3.pic' }, { filename +=> 'bar4.pic' } ] } # for fil +e_row ] # for dir_row } ];
Plug this in the code to see your output. Notice here that I have simply added an extra anonymous hash to the dir_row array of the first directory.

_____________________
$"=q;grep;;$,=q"grep";for(`find . -name ".saves*~"`){s;$/;;;/(.*-(\d+) +-.*)$/; $_=["ps -e -o pid | "," $2 | "," -v "," "];`@$_`?{print"+ $1"}:{print" +- $1"}&&`rm $1`; print$\;}

Replies are listed 'Best First'.
Building the structure to hold said beast.
by LTjake (Prior) on May 30, 2002 at 11:54 UTC
    Sorry about the previous anonymous posts -- i couldn't get my password at the machine I was using.

    Anyway, my next (logical) follow-up question is this: Given an array of directories (@dirs) and the ability to get all of the filenames in each of those dirs into an array (@files), what's the best way to build the structure you describe in your post?

    would you do something like:
    foreach (@dirs) { # get filenames into @files # push dir name...? foreach (@files) { # do some sort of magic with push();, # taking into account when you get to the # fifth filename...? } }
    I was able to figure out how to use push() to loop through the dir names, but adding the sub-structures is confusing :)

    -Brian
      LTjake, give this a shot:
      #!/usr/bin/perl use strict; use File::Find; use Data::Dumper; my $dir_list; # count of { file_row => [...] } entries inside # dir_row array. (err.. simply dir_row array's size). my $dir_row_count = 0; my $file_count = 0; # number of files in a row.. my $file_split_count = 5; # previous directory my $prev_dir; find(\&wanted, 'data'); print Dumper($dir_list); ### SUBS sub wanted { $DB::single = 1; unless ($prev_dir eq $File::Find::dir) { $prev_dir = $File::Find::dir; # got a new directory push @$dir_list, { dir => $File::Find::dir, dir_row => [] }; } if (-f $_) { unless ($file_count % $file_split_count) { # add another file row if maximum number of files # allowed in a row has been exceeded. push @{$dir_list->[scalar @$dir_list - 1]{dir_row}}, { file_row +=> [] }; } # add file to the file row... push @{$dir_list->[scalar @$dir_list - 1]{dir_row}[$dir_row_count] +{file_row}}, { filename => $File::Find::name }; $dir_row_count++; $file_count++; } }
      Unfortunately, this is an untested piece as I have no 'good' means to thoroughly test it on the box I"m on now (my MS-DOS command prompt doesn't work for some freakn reason.. ). I'll do the testing on my Unix box at work (during coffee time, yeah! ;-)

      Note: I post it here in hopes someone picks it up from where I left or at leats finds it useful in his own rendition of a solution. (although, having this reply nested so deep, I'm not sure if many monks out there will notice it ;)

      _____________________
      $"=q;grep;;$,=q"grep";for(`find . -name ".saves*~"`){s;$/;;;/(.*-(\d+) +-.*)$/; $_=["ps -e -o pid | "," $2 | "," -v "," "];`@$_`?{print"+ $1"}:{print" +- $1"}&&`rm $1`; print$\;}
      It's not exactly clear what you're after. Can you add links to your original Anonymous posts? That way we'll be able to respond to your posts more efficiently.

      --t. alex

      "Nyahhh (munch, munch) What's up, Doc?" --Bugs Bunny