Category: CGI Programing
Author/Contact Info Houblon
Description: I had to make many tables with a special font face. Instead of writing the font code in each cell I made up this object that print a table. I'm not an experienced perl programmer so, I'm sure there is better way to do it, but it's working well for me and if any one what's to use, go ahead. Any suggestion to make it better will still be appreciate.
#!/usr/bin/perl -w use strict; use CGI qw/:standard :html3/; use TableMaker; my $query = new CGI; my $table_hello = new TableMaker; $table_hello->width(300); $table_hello->cols(2); $table_hello->border(1); $table_hello->face('Verdana, Arial, Helvetica'); $table_hello->addCell({-color=>'#FF0000', -align=>'center'}, h3('Hello')); $table_hello->addCell({-align=>'center'},h3('World')); $table_hello->addCell({-align=>'center', -colspan=>'2'},h3('Hello World')); $table_hello->addCell({-default=>''},'Salut'); $table_hello->addCell('Salut'); print $query->header; print $query->start_html(-title=>'TableMaker.pm', -BACKGROUND=>'', -BGCOLOR=>'#000000', -TEXT=>'#FFFFCC', -LINK=>'#00FFFF', -VLINK=>'#66CC00', -ALINK=>'#CC00FF'); print $table_hello->print_table(); print $query->end_html;
package TableMaker;
use strict;
use vars '$AUTOLOAD';
use CGI qw/:standard :html3/;

sub new {
  my $this = shift;
  my $class = ref($this) || $this;
  my $self = {};
  $self->{face} = undef;
  $self->{color} = undef;
  $self->{size} = undef;
  $self->{width} = undef;
  $self->{border} = undef;
  $self->{cellspcacing} = undef;
  $self->{cols} = 1;
  $self->{cells} = [];
  bless($self, $class);
  return $self;
}

sub AUTOLOAD {
  no strict 'refs';
  my ($self, $val) = @_;
  my ($name) = $AUTOLOAD =~ m/.*::(\w*)/;

  return defined $val ? $self->{$name} = $val : $self->{$name};
}

sub addCell {
  my $self = shift;
  my @opt = qw/text face color size colspan rowspan align valign width
+ height/;
  my (%font, %td);
  my ($cs, $rs);
  if ( ref($_[0]) eq "HASH" ) {
    foreach ( @opt ) {
      if ( $_ =~ /text|face|color/ ) {
        if ( $_[0]->{$_} ) {
          $font{$_} = $_[0]->{$_}
        } elsif ( $_[0]->{"-$_"} ) {
          $font{$_} = $_[0]->{"-$_"}
        }elsif ( $self->{$_} ) {
          $font{$_} = $self->{$_}
        }
      } elsif ( $_ eq 'colspan' ) {
        if ( $_[0]->{$_} ) {
      $td{$_} = $_[0]->{$_};
      $cs = $_[0]->{$_}
    } elsif ( $_[0]->{"-$_"} ) {
      $td{$_} = $_[0]->{"-$_"};
      $cs = $_[0]->{"-$_"}
    }
      } elsif ( $_ eq 'rowspan' ) {
        if ( $_[0]->{$_} ) {
      $td{$_} = $_[0]->{$_};
      $rs = $_[0]->{$_}
    } elsif ( $_[0]->{"-$_"} ) {
      $td{$_} = $_[0]->{"-$_"};
      $rs = $_[0]->{"-$_"}
    }
      } elsif ( $_[0]->{$_} ) {
          $td{$_} = $_[0]->{$_};
      } elsif ( $_[0]->{"-$_"} ) {
          $td{$_} = $_[0]->{"-$_"};
      }
    }
  if (%font) {
    push(@{ $self->{cells} }, [td(\%td,font(\%font,$_[1])), $cs, $rs ]
+);
  } else {
    push(@{ $self->{cells} }, [td(\%td,$_[1]), $cs, $rs ]);
  } 
  } else {
    push(@{ $self->{cells} }, [td($_[0]), $cs, $rs ]);
  }
  
}

sub print_table {
  my $Rows;
  my $self = shift;
  my $col = 1;
  my @tab_opt = qw/width border cellspacing/;
  my %tab_opt;
  foreach (@tab_opt) {
    if ( $self->{$_} ) {
      $tab_opt{$_} = $self->{$_}
    } 
  }
  my @rowspan;
  my $row;
  my $colspan;
  foreach ( @{ $self->{cells} } ) {
    if ( $self->{cols} == 1 ) {
      $Rows .= Tr($_->[0])
    } else {
      while ( $rowspan[$col] ) {
    $rowspan[$col]--;
    if ( $col < $self->{cols} ) {
      $col++;
    } else {
          $Rows .= Tr($row);
      $row = ' ';
      $col = 1;
    }
      }
      $row .= $_->[0];
      $colspan = $_->[1] ? $col + $_->[1] - 1 : $col;
      $colspan = $self->{cols} if $colspan > $self->{cols};
      while ( ($col <= $colspan) ) {
    $rowspan[$col] = $_->[2] - 1 if $_->[2];
        $col++;
      }
      unless ( $col <= $self->{cols} ) {
        $Rows .= Tr($row);
    $row = ' ';
    $col = 1;
      }
    }
  }
  while ( $col <= $self->{cols} ) {
    unless ( $rowspan[$col++] ){
      $row .= td(' ')
    }
  }
  $Rows .= Tr($row);
  return table(\%tab_opt,$Rows);
    
}

1;
Replies are listed 'Best First'.
RE: TableMaker
by davorg (Chancellor) on Jul 10, 2000 at 23:44 UTC

    I'd like to make a few suggestions for improving this useful module.

    1. You should use the second argument to bless in case someone wants to subclass this class.
    2. All of the attribute accessor functions are identical. Is there potential to make them all one function - or perhaps to do something clever in AUTOLOAD.
    3. The addCell function takes rather a lot of parameters. It might be easier to use if you used named parameters rather than positional ones.
    4. code like push(@font, " $opt$i=\"" . $self->{$opt$i} . "\"") might be easier to understand if it was written as push(@font, qq( $opt$i="$self->{$opt$i}")).
    5. Why not use the CGI.pm table creation functions to build your table elements?

    Hope you find this helpful. Let me know if I can clarify anything.

    --
    <http://www.dave.org.uk>

    European Perl Conference - Sept 22/24 2000, ICA, London
    <http://www.yapc.org/Europe/>
      Thank you for your suggestion. And sure, you will have to clarify, if you don't mind.
      1. I still don't understand the use of bless.
      2. First time I hear about AUTOLOAD. I read a little about it, but I still don't know how to call it.
      3. You're probably right. Even if it's faster for me to use it this way now, I guess it's more the Perl way of doing it.
      4. Didn't know about the qq function. I'll try to use it properly.
      5. I didn't use the CGI.pm table creation functions cause I don't how to put the parameters programely in the table or td functions.
      I guess I would need to read a good book about Perl OO. But when I applied to a job where I am, it was as Video Editor.

        OK, but this may be a looong post :)

        1. bless 'registers' a reference as being of a certain type (or class). The type to use is passed as the optional second parameter. If the second parameter is omitted, it defaults to the name of the current package. bless is most often (always?) used in the constructor of an object, so that the object carries with it its type. If you create a subclass which inherits the constructor of another class, then unless you use the two parameter version of bless, the object will be blessed with the type of the superclass, not your class.
        2. AUTOLOAD is a special function which (if it exists) is called when an unknown method is called on an object. It's very powerful and you can use it to do all sorts of deep magic!
        3. Named parameters are a very neat trick to learn. Basically you treat @_ as a hash.
        4. qq() is an operator rather than a function. Find info about it in perldoc perlop.
        5. All CGI.pm HTML functions take an optional ref to a hash containing attributes as their first parameter.

        Let me know if I can be any more help.

        --
        <http://www.dave.org.uk>

        European Perl Conference - Sept 22/24 2000, ICA, London
        <http://www.yapc.org/Europe/>