Re: checkbox help
by Herkum (Parson) on Mar 05, 2007 at 18:21 UTC
|
When you are working with checkboxes, you should already know what boxes are going to to appear on the form.
It is easy for a someone to slip something onto the web page manually and typos can also be an issue.
On this case, be explicit, know exactly which entries are supposed to be on the form rather than loop through doing a regular expression on the input names.
| [reply] |
|
|
it's done like this so that the code is portable, it can read in any HTML template.
| [reply] |
|
|
my $checkbox_fields = get_checkbox_fields();
for my $field (@{$checkbox_fields}) {
$in{$field} = $query->param($field) ? 'checked' : 'not checked';
}
sub get_checkbox_fields {
return [qw(c_test1 c_test2 c_test3)]
}
If you use the get_checkbox_fields() to generate the checkboxes on your web page, then you can use it to verify the data you get from the web page.
Looping through the fields using a regexp can lead to errors with conflicting field names or someone inserting extra fields into the submission. You can never rely on a naming convention to classify data you receive from a web page. Always know exactly what you expect and you do not have to worry about these sorts of issues.
| [reply] [d/l] |
Re: checkbox help
by Anno (Deacon) on Mar 05, 2007 at 18:23 UTC
|
There's too little context for a reasonable atempt to explain the code. For one, the sequence doesn't look right. The first part (you call it a "switch", what do you mean by that?) assumes that %checked already has values. But the values are only set in the code you say runs later. Mind, it may still make sense but it is hard to guess what that could be.
Why does it matter whether actual text appears in the tab-delimited data? The delimiters make it clear that a field is there, even if there's no data in it.
If you must (untested):
if ($_=~/^c_/) {
$check{$_}="CHECKED"
print OUT $in{ $_} ? $in{$_} : '-no data-', "\t";
Your question "Why is $check{$_} being set to "CHECKED" everytime?" doesn't make much sense. $check{$_} is a different hash field every time, it isn't set again and again. As for why this is done, you are in a better position to guess than anyone else.
Anno
| [reply] [d/l] [select] |
|
|
Here's the whole program,...
#!/usr/bin/perl
use strict;
use CGI;
use Mail::Sendmail;
use File::Basename;
use MIME::Base64;
my $SERVER="http://".$ENV{'SERVER_NAME'};
my $form=$SERVER.$ENV{'SCRIPT_NAME'} || $SERVER.$ENV{'PATH_INFO'};
my $datapath=dirname $0;
my $progname=basename$0;
my $smtp = "appsmtp.ottawa.ca";
my ($sec,$min,$hr,$day,$mon,$yr)=(localtime);
my $today=sprintf("%04d-%02d-%02d %02d:%02d", $yr+1900, $mon+1, $day,
+$hr, $min);
my $date;
my $start_hide;
my $end_hide;
my $xls_file = "$datapath/working/file.xls";
my %in=();
my %str=();
my %check=();
my $typetext="text";
my $typetextarea="textarea";
my $closetextarea="<\/textarea>";
my $border=0;
my $SENDSTR;
my $reset;
my $ATTACHSTR;
my $MAIL_TO='bryson.connolly@ottawa.ca';
my $submitstr;
my %mainbody;
my $formid;
my $debug =0;
my $new_form;
#------------------
#read form input
#------------------
my $query=new CGI;
my $action=$query->param('action');
my $lang=$query->param('lang');
$formid=&newformid;
if ($lang ne "_fr")
{ $lang="_en";
$SENDSTR="Submit";
$reset="Reset";
$ATTACHSTR='';
}
else
{
$SENDSTR="Soumettre";
$reset="reset";
$ATTACHSTR='';
}
my $tpl = "registration$lang.html";
$submitstr="<input type=submit name=action value=\"$SENDSTR\"> "
+;
$reset="<INPUT type=reset value=Reset name=resetbutton> ";
print "Content-type: text/html\n\n";
&getdata;
if ($action eq $SENDSTR)
{
$typetext="hidden";
$typetextarea="input type=hidden";
$closetextarea="";
%str=%in;
$submitstr="";
$reset="";
$ATTACHSTR="";
$date=$today;
mailto($query);
}
my $tmp= &readhtml("$datapath/$tpl");
#$tmp=&doclean($tmp);
print $tmp;
exit;
#return htmlfile from template
sub readhtml
{
my $selectname;
my $retfile;
open (DATA, "@_") || print "@_ file not found";
while (<DATA>)
{
#parse input data
#input type must be specified
#type specified right after <input
#name must only contain "A-Za-z0-9_"
s|<input type=text([^>]?name=)"?(\w+)"?(.*?>)|<input type=$typ
+etext $1$2 value="$in{$2}" $3 <b><tt>$str{$2}</tt></b>|ig;
#s|<textarea([^>]?)name=(\w+)(.*?>)|<$typetextarea $1 name=$2
+value="$in{$2}"$3$in{$2}|ig;
s|<textarea(.*)name="?(\w+)"?(.*?>)|<$typetextarea $1 name=$2
+value="$in{$2}" $3 $in{$2}|ig;
s|</textarea>|$closetextarea|ig;
s|(<input type=radio)(.*)( name=)(\w+)( value="?)([\w\.\s\~]+)
+("?)|$1$2$3$4$5$6$7 $check{$4.$6}|ig;
s|(<input type=checkbox)(.*)( name=)(\w+)|$1$2$3$4 $check{$4}|
+ig;
s/(\$[\w{}]+)/$1/eeg;
#now to do the selects
if ( /<select name="?(\w+)"?/ig ) {$selectname=$1}
s/(<option value="?)([\w\@\,\;\.\s\&\/]+)("?)(.*?>)/$1$2$3 $ch
+eck{$selectname.$2}$4/ig;
s|<option>(.*)</option>|
package temp;
my $tmp;
if ( ($check{$selectname.$1}) or ($typetext eq "text") )
{ $tmp="<option $check{$selectname.$1}>$1</option>";
+ }
$tmp
|sgeix;
$retfile.=$_;
}
close (DATA);
return $retfile;
}
sub getdata { # $_ is the form element name and $in{$_} is the cont
+ents.
if ($action eq $SENDSTR) {
open(OUT,">>$xls_file") || print "could not open $xls_file"
+ ;
}
foreach ($query->param)
{
$in{$_} = $query->param($_);
if ($_=~/^c_/) { $check{$_}="CHECKED" } #chec
+kbox
if ($_=~/^r_/) { $check{$_.$in{$_}}="CHECKED" } #radi
+o
if ($_=~/^s_/) { $check{$_.$in{$_}}="SELECTED" } #Sel
+ect
if ($action eq $SENDSTR) {
$in{$_}=~s/\r\n/ /g;
if ($_ !~/action|lang/) { # don't print these fields to X
+LS file
print OUT "$in{$_}\t";
}
}
$in{$_}=~s/\r\n/<br>/g || $in{$_}=~s/<br>/\n/g;
$in{$_}=~s/"/"/g;
$in{$_}=~s/'/’/g;
$in{$_}=~s/\$/&\#36;/g;
} # end foreach
if ($action eq $SENDSTR) {
print OUT "$today\t";
print OUT "\n";
close(OUT);
}
}
sub mailto
{
blah blah,,,send mail
}
sub newformid
{
use File::CounterFile;
$File::CounterFile::DEFAULT_DIR="$datapath/working";
my $c = File::CounterFile->new("counter.dat");
return $c->inc;
}
sub doclean
{
#remove the hidden fields and submit/reset buttons
($_)=@_;
undef $/;
s|<input (type=hidden.*?)>|<skip $1>|imsg;
s|<input type="+submit.*?>||imsg;
s|<input type="+reset.*?>||imsg;
$/="\n";
return $_;
}
So, I want to print "do data" when the checkbox isn't checked. An easier way would be to just name all the checkboxes different. Ex: check1_checked. It won't line up in the spreadsheet, but the data will be there. although, I wouldn't mind figuring out how to print "do data" when it's not checked. I understand that it's not in the param list when it's blank... just trying to figureout the best way to trap that without messing with the program too much. | [reply] [d/l] |
|
|
thanks for your help guys... i'll just give all the checkboxes descriptive names and those names will be written to the file so i'll know what's checked... just won't line up... but whatever. I'm not re-writing the program just for that.
| [reply] |
|
|
|
|
print OUT defined($in{$_}) ? $in{$_} : '-no data-', "\t";
Furthermore, your approach won't work. According to the HTML spec (and verified with a few browsers),
A switch is "on" when the control element's checked attribute is set. When a form is submitted, only "on" checkbox controls can become successful.
That means that only checked checkboxes are submitted. defined($in{$_}) will always be true.
| [reply] [d/l] [select] |
|
|
Yeah, sloppy work. Especially since your own first reply reply was already there and might have alerted me. I'll go do something else now.
Anno
| [reply] |
|
|
| [reply] |
Re: checkbox help
by ikegami (Patriarch) on Mar 05, 2007 at 18:05 UTC
|
but I want it to write something like "no data" so that everything lines up.
if (/^c_/) {
$check{$_} = "CHECKED"
print OUT "$in{$_}\t";
} else {
print OUT "no data\t"; # or just "\t"
}
why is $check{$_} being set to "CHECKED" everytime?
The checkbox will only be present in the list of params if it is checked.
| [reply] [d/l] |
|
|
that didn't work.... because i'm printing out more than just checkbox data. Here's the whole sub routine:
sub getdata { # $_ is the form element name and $in{$_} is the cont
+ents.
if ($action eq $SENDSTR) {
open(OUT,">>$xls_file") || print "could not open $xls_file" ;
}
foreach ($query->param)
{
$in{$_} = $query->param($_);
if ($_=~/^c_/) { $check{$_}="CHECKED" } #checkbox
if ($_=~/^r_/) { $check{$_.$in{$_}}="CHECKED" } #radio
if ($_=~/^s_/) { $check{$_.$in{$_}}="SELECTED" } #Select
if ($action eq $SENDSTR) {
$in{$_}=~s/\r\n/ /g;
if ($_ !~/action|lang/) { # don't print these fields to X
+LS file
print OUT "$in{$_}\t";
}
}
$in{$_}=~s/\r\n/<br>/g || $in{$_}=~s/<br>/\n/g;
$in{$_}=~s/"/"/g;
$in{$_}=~s/'/’/g;
$in{$_}=~s/\$/&\#36;/g;
} # end foreach
if ($action eq $SENDSTR) {
print OUT "$today\t";
print OUT "\n";
close(OUT);
}
}
| [reply] [d/l] |
|
|
I have no idea what I was thinking when I wrote the first part of that post. Like I said in the second half, unchecked checkboxes are not in the list of params. As per the HTML spec, they are not sent by the client to the server. You need to loop over the fields you want to output, not over the params
my @fields = qw(
...
c_...
c_...
c_...
...
);
foreach (@fields)
{
$in{$_} = $query->param($_);
if (/^c_/ && defined($in{$_})) {
$check{$_} = "CHECKED";
}
...
}
| [reply] [d/l] |