Lady_Aleena has asked for the wisdom of the Perl Monks concerning the following question:

Hello everyone...

I am writing a script to create a browser based interface for my data. The script, when done, will hopefully do the following.

  1. Overwrite the data file with the updated data.
  2. Reload the script with the updated data.

Now, I have the HTML down, but I am not exactly sure on how to create all of the $cgi->(param) variables I would need. I am pretty sure that I shouldn't try to manually create each and every one, but I am not sure how to create them in the loop(s).

The following is all of the code that goes with the script, and you can find the data here. I included two of the subroutines from the home rolled modules I used in this. start_html and end_html do just that. start_html is just a bit much to add. :)

So, if I could get a nudge (or push/shove) into the right direction on how to get the script to do the above list, that would be great. I would like to be able to add new data lines with this too, but I am pretty sure if that is not possible with the way the code is currently written.

Thanks for reading!

The script

use strict; use warnings; use CGI; use List::Util qw(max); use lib "C:/Documents and Settings/Dawn/My Documents/fantasy/files/per +l/lib"; use Base::HTML qw(start_html end_html line); use Base::GetDir qw(data_directory); use Base::CSV::Hash qw(get_hash); my %movies; my %movies_data = ( 'csv' => data_directory("Movies")."movies.csv", 'headings' => [qw(id title first_year last_year wiki amg imdb tvcom +flixster genre theme type own)], ); get_hash(\%movies,\%movies_data); my %text_inputs = ( general => [qw(id title first_year last_year genre theme)], external_links => [qw(wiki amg imdb tvcom flixster)], ); my %radio_lists = ( type => [qw(film miniseries television_program)], own => [qw(blue-ray dvd vhs)], ); sub title_length { my @lengths; for my $movie (keys %movies) { push @lengths, length($movies{$movie}{title}); } my $length = max(@lengths); return $length; } start_html('','','no'); line(3,qq(<form action="Movie.pl" method="get">)); for my $movie (sort keys %movies) { my $length = title_length(); my $title = $movies{$movie}{title} ? $movies{$movie}{title} : $movie +s{$movie}{id}; line(4,qq(<h2 class="title" style="clear:both;">$title</h2>)); line(4,qq(<div>)); for my $group (keys %text_inputs) { my $legend = ucfirst $group; $legend =~ s!_! !g; line(5,qq(<fieldset style="float:left;">)); line(6,qq(<legend>$legend</legend>)); for my $heading (@{$text_inputs{$group}}) { my $print_heading = $heading; $print_heading =~ s!_! !; my $label_id = $movies{$movie}{id}.'_'.$heading; $label_id =~ s! !_!g; line(6,qq(<div>)); line(7,qq(<label class="block" for="$label_id">$print_heading:</ +label>)); line(7,qq(<input id="$label_id" class="block" type="text" size=" +$length" value="$movies{$movie}{$heading}">)); line(6,qq(</div>)); } line(5,qq(</fieldset>)); } line(5,qq(<div>)); for my $key (keys %radio_lists) { line(6,qq(<fieldset>)); line(7,qq(<legend>$key</legend>)); for my $type (@{$radio_lists{$key}}) { my $checked = ""; #The following commented out code causes the script to hang up in my b +rowser. It is supposed to print " checked" on the radio button with t +he same value as the movie has if any. # if ($movies{$movie}{$key} eq $type) { # $checked = " checked"; # } my $print_heading = $type; $print_heading =~ s!_! !; my $label_id = $movies{$movie}{id}.'_'.$type; $label_id =~ s! !_!g; line(7,qq(<div>)); line(8,qq(<input id="$label_id" type="radio" name="$key" value=" +$type"$checked >)); line(8,qq(<label for="$label_id">$print_heading</label>)); line(7,qq(</div>)); line(6,qq(</fieldset>)); } line(5,qq(</div>)); line(4,qq(</div>)); } line(4,qq(<div style="clear:both"><input type="submit" value="submit"> +</div>)); line(3,qq(</form>)); end_html();

sub line from my Base::HTML module

sub tab { my ($var) = @_; return ("\t") x $var; } sub line { my ($tab,$var) = @_; print tab($tab).$var."\n"; }

My Base::CSV::Hash module

package Base::CSV::Hash; use strict; use warnings; use base 'Exporter'; our @EXPORT_OK = qw(get_hash); sub open_file { my ($file) = @_; open(my $fh, $file) or die("can't open $file $!"); my @lines = <$fh>; chomp(@lines); return @lines; } sub get_hash { my ($hash,$data_hash) = @_; my @data = open_file($data_hash->{csv}); for my $value (@data) { my @inner_array = split(/\|/,$value); my $n = 0; for my $heading (@{$data_hash->{headings}}) { $$hash{$inner_array[0]}{$heading} = $inner_array[$n]; ++$n; } } } 1;
Have a cookie and a very nice day!
Lady Aleena

Replies are listed 'Best First'.
Re: Creating a browser based script to update a data file
by zentara (Cardinal) on Aug 05, 2010 at 16:19 UTC
    Update: Mother warns of old Vars() method, so original post changed:

    You could do:

    #!/usr/bin/perl use warnings; use strict; use CGI; print "Content-type: text/html\n\n"; # from perldoc CGI my $query=CGI->new; print "<h2>Current Values</h2> $query\n"; #or #print Dump;
    That would at least give you a way to test your html form fields, like 'file', with which you can experiment.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku

      Vars is a compatibility method for the perl4 lib, IIRC and should be avoided (as should indirect method call on new). To dump your input, just use, drumroll... Dump. It formats form input into HTML lists and handles multiple values per key.

Re: Creating a browser based script to update a data file
by toolic (Bishop) on Aug 05, 2010 at 16:43 UTC
    This in no way helps to answer your question, but here is an unsolicited refactoring of your title_length sub. Whenever I see the for/push combo, I think of map:
    sub title_length { return max( map { length $movies{$_}{title} } keys %movies ); }

      toolic, even though it is unsolicited, it is very good advice. I keep forgetting that there are more ways to loop iterate than for. I could find myself doing something akin to...

      my @list = qw(oof rab zab); my $last = pop(@list); for my $thing (@list) { print $thing.'-'; } print $last;

      instead of...

      my @list = qw(oof rab zab); print join('-',@list);

      Ridiculous, I know, but I have probably written similar code plenty of times. My overdependence on for has lead to longer and probably more agonizing code. So, thank you for reminding me of a simpler way to do that loop and other loops I may have that are just like it!

      Have a cookie and a very nice day!
      Lady Aleena