# HTML::Macro::Loop; Loop.pm
# Copyright (c) 2001,2002 Michael Sokolov and Interactive Factory. All rights
# reserved. This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
package HTML::Macro::Loop;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require Exporter;
require AutoLoader;
@ISA = qw(Exporter AutoLoader);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@EXPORT = qw(
);
$VERSION = '1.04';
# Preloaded methods go here.
sub new ($$$)
{
my ($class, $page) = @_;
my $self = {
'vars' => [],
'rows' => [],
'@parent' => $page,
};
bless $self, $class;
return $self;
}
sub declare ($@)
# use this to indicate which vars are expected in each iteration.
# Fills the vars array.
{
my ($self, @vars) = @_;
@ {$$self {'vars'}} = @vars;
}
sub push_array ($@)
# values must be pushed in the same order as they were declared, and all
# must be present
{
my ($self, @vals) = @_;
die "HTML::Macro::Loop::push_array: number of vals pushed(" . (@vals+0) . ") does not match number declared: " . (@ {$$self{'vars'}} + 0)
if (@vals + 0 != @ {$$self{'vars'}});
my $row = &new_row;
my $i = 0;
foreach my $var (@ {$$self{'vars'}})
{
$row->set ($var, $vals[$i++]);
}
push @ {$$self{'rows'}}, $row;
}
sub new_row
{
my ($self) = @_;
my $row = new HTML::Macro;
$row->set ('@parent', $self);
$row->{'@attr'} = $self->{'@parent'}->{'@attr'};
$row->{'@incpath'} = $self->{'@parent'}->{'@incpath'};
return $row;
}
sub pushall_arrays ($@)
# values must be pushed in the same order as they were declared, and all
# must be present. Arg is an array filled with refs to arrays for each row
{
my ($self, @rows) = @_;
foreach my $row (@rows) {
$self->push_array (@$row);
}
}
sub push_hash ($$)
# values passed with var labels so they may come in any order and some may be
# absent (in which case zero is subtituted). However, any values passed whose
# vars were not declared are -silently- ignored unless there has been no
# declaration, in which case the keys of the hash are accepted as an implicit
# declaration.
{
my ($self, $pvals) = @_;
my @ordered_vals;
my $row = &new_row;
$self->declare (keys %$pvals) if (!@ {$$self{'vars'}}) ;
my $i = 0;
foreach my $var (@ {$$self{'vars'}})
{
$row->set ($var, defined($$pvals{$var}) ? $$pvals{$var} : '');
}
push @ {$$self{'rows'}}, $row;;
}
sub set ($@ )
# set more values in the most recent row, or add a row if none exists
{
my $self = shift;
if (! $$self{'rows'} )
{
$self->push_hash (\@_);
} else {
my $rows = $$self{'rows'};
my $row = $$rows[$#$rows];
$row->set (@_);
}
}
sub set_hash ($$ )
# set more values in the most recent row, or add a row if none exists
{
my $self = shift;
if (! $$self{'rows'} )
{
$self->push_hash (@_);
} else {
my $rows = $$self{'rows'};
my $row = $$rows[$#$rows];
$row->set_hash (@_);
}
}
sub doloop ($$ )
# perform repeated processing a-la HTML::Macro on the loop body $body,
# concatenate the results and return that.
{
my ($self, $body) = @_;
my $buf = '';
foreach my $row (@ {$$self{'rows'}})
{
my $iteration;
$row->{'@cwd'} = $self->{'@parent'}->{'@cwd'};
$buf .= $row->process_buf ($body);
}
return $buf;
}
sub new_loop ()
{
my ($self, $name, @loop_vars) = @_;
my $rows = $$self{'rows'};
die "HTML::Loop::new_loop: no rows in loop - call a push method" if !@$rows;
my $new_loop = new HTML::Macro::Loop ($$rows [$#$rows]);
if ($name) {
$self->set ($name, $new_loop);
}
if (@loop_vars) {
$new_loop->declare (@loop_vars);
}
return $new_loop;
}
sub is_empty ()
{
my ($self) = @_;
return ! ($self->{'rows'} && (@ {$self->{'rows'}} > 0));
}
sub keys ()
{
my ($self) = @_;
return () if $self->is_empty();
my $rows = $$self{'rows'};
return ($$rows [$#$rows])->keys();
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
# Below is the stub of documentation for your module. You better edit it!
=head1 NAME
HTML::Macro::Loop - looping construct for repeated HTML blocks
=head1 SYNOPSIS
use HTML::Macro;
use HTML::Macro::Loop;
$htm = HTML::Macro->new();
$loop = $htm->new_loop('loop-body', 'id', 'name', 'phone');
$loop->push_array (1, 'mike', '222-2389');
$loop->push_hash ({ 'id' => 2, 'name' => 'lou', 'phone' => '111-2389'});
$htm->print ('test.html');
=head1 DESCRIPTION
HTML::Macro::Loop processes tags like
loop body
Each loop body is treated as a nested HTML::Macro within which variable
substitutions, conditions and nested loops are processed as described under
HTML::Macro. For complete documentation see HTML::Macro.
=head1 AUTHOR
Michael Sokolov, sokolov@ifactory.com
=head1 SEE ALSO HTML::Macro
perl(1).
=cut