Beefy Boxes and Bandwidth Generously Provided by pair Networks Joe
There's more than one way to do things
 
PerlMonks  

Creating HTML radio button group with text field

by impossiblerobot (Deacon)
on May 05, 2002 at 01:03 UTC ( #164082=perlquestion: print w/ replies, xml ) Need Help??
impossiblerobot has asked for the wisdom of the Perl Monks concerning the following question:

Since I generally prefer my HTML to look like HTML, I tend to use templates and here-docs, and eschew CGI.pm's HTML-generation features.

However, on my current project, I think these features could be useful -- if I can figure out how to do what I need to do. :-)

A fairly common feature in forms/surveys is a radio-select with an "Other" option, and a text field attached to the "Other" option, as follows:

What is your favorite number?<br> <input type="radio" name="question" value="a">5</input><br> <input type="radio" name="question" value="b">7</input><br> <input type="radio" name="question" value="c">13</input><br> <input type="radio" name="question" value="d">Other (please specify:)< +/input> <input type="text" name="other"><br>
I need to be able to optionally add (for example) a text field to any of the radio options. Does anyone know of a clean way to do this with CGI.pm, or am I better off writing my own HTML-generation routine?

Impossible Robot

Comment on Creating HTML radio button group with text field
Download Code
Re: Creating HTML radio button group with text field
by Popcorn Dave (Abbot) on May 05, 2002 at 01:25 UTC
    I ran in to a similar ( I think :] ) problem on a script I was doing for an HTML page that would allow the user to update items for sale, and delete them when they were sold.

    Since I had checkboxes, I needed a way to make them unique. I ended up doing generation on the fly manually. There was no way for CGI.pm to do it as I was basically saying 'd'.$index, and I was incrementing index for every item in the base file.

    So in answer to your question, if you need it to be on the fly, you're probably going to have to do it by hand. It makes your not quite as clean as CGI.pm is going to make it look, but them's the breaks :)

    Hope that helps you out.

(jeffa) Re: Creating HTML radio button group with text field
by jeffa (Chancellor) on May 05, 2002 at 01:38 UTC
    Other then omitting the <br> tag in between the last radio box and the text box, this should do the trick get you started. Personally, i would use HTML::Template instead. This is some hairy code :P
    use strict; use CGI qw(:standard); use CGI::Pretty; my @question = ('a'..'d'); my $answer = [ [('number',5,7,13)], [('color','red','green','fuschia')], ]; print header, start_html, start_form; foreach my $i (0..$#$answer) { # remove type of question from front and add 'Other' to end my $thingy = shift @{$answer->[$i]}; push @{$answer->[$i]}, 'Other (please specify)'; print "What is your favorite $thingy?", br, radio_group( -name => sprintf('%s%02d','question',$i + 1), -labels => { map { $question[$_] => $answer->[$i]->[$_] } (0..$#question)}, -values => \@question, -linebreak => 'true', ), textfield(sprintf('%s%02d','other',$i + 1)), p; } print submit, end_form, end_html;

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Thanks, jeffa, but this doesn't quite meet my requirements. I'm sorry if my question wasn't clear. As I said in my original post (but did not include in my HTML sample):
      I need to be able to optionally add (for example) a text field to any of the radio options.
      Here's another example to clarify:
      Where did you hear about this product? <input type="radio" name="question" value="a">Friend</input><br> <input type="radio" name="question" value="b">Magazine (please specify +:)</input> <input type="text" name="magname"><br> <input type="radio" name="question" value="c">Brochure</input><br> <input type="radio" name="question" value="d">Other (please specify:)< +/input> <input type="text" name="other"><br>
      I hope this makes it clearer what I want to be able to do.

      Impossible Robot
        Sorry impossiblerobot - i indeed did miss that rather clear requirement. How about a cleaner HTML::Template solution?
        use strict; use CGI qw(header); use HTML::Template; my $data = do {local $/; <DATA>}; my $template = HTML::Template->new( scalarref => \$data, ); $template->param( questions => [ { question => 'What is your favorite number?', radio => [ { regular => 'question01', value => 'a', label => 5, }, { regular => 'question01', value => 'b', label => 7, }, { regular => 'question01', value => 'c', label => 13, }, { special => 'question01', value => 'd', label => 'Other', text => 'other', }, ], }, { question => 'Where did you hear about this product?', radio => [ { regular => 'question02', value => 'a', label => 'Friend', }, { special => 'question02', value => 'b', label => 'Magazine', text => 'magname', }, { regular => 'question02', value => 'c', label => 'Brochure', }, { special => 'question02', value => 'd', label => 'Other', text => 'other', }, ], }, ], ); print header, $template->output; __DATA__ <form> <tmpl_loop questions> <p> <tmpl_var question><br/> <tmpl_loop radio> <tmpl_unless special> <input type="radio" name="<tmpl_var regular>" value="<tmpl_va +r value>"/><tmpl_var label><br/> <tmpl_else> <input type="radio" name="<tmpl_var special>" value="<tmpl_va +r value>"/><tmpl_var label> (please specify:) <input type="text" name="<tmpl_var text>"/><br/> </tmpl_unless> </tmpl_loop> </p> </tmpl_loop> <input type="submit"> </form>
        Now for the fun part - getting the right values out! You might want to prefix each text box with the letter and call them all 'other'. For example, instead of calling the Magazine textbox 'magname', call it something along the lines of 'b-other' so you can dynamical retrieve it from CGI::param(). This is just off the top of my head (/me winks at BUU), but you get the point. Good luck!

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
(podmaster) Re: Creating HTML radio button group with text field
by PodMaster (Abbot) on May 05, 2002 at 01:58 UTC
    Straight from the guts of CGI.pm, where you should've had at least one visit ;)
    #### Method: radio_group # Create a list of logically-linked radio buttons. # Parameters: # $name -> Common name for all the buttons. # $values -> A pointer to a regular array containing the # values for each button in the group. # $default -> (optional) Value of the button to turn on by default. + Pass '-' # to turn _nothing_ on. # $linebreak -> (optional) Set to true to place linebreaks # between the buttons. # $labels -> (optional) # A pointer to an associative array of labels to print nex +t to each checkbox # in the form $label{'value'}="Long explanatory label". # Otherwise the provided values are used as the labels. # Returns: # An ARRAY containing a series of <INPUT TYPE="radio"> fields #### 'radio_group' => <<'END_OF_FUNC', sub radio_group { my($self,@p) = self_or_default(@_); my($name,$values,$default,$linebreak,$labels, $rows,$columns,$rowheaders,$colheaders,$override,$nolabels,@oth +er) = rearrange([NAME,[VALUES,VALUE],DEFAULT,LINEBREAK,LABELS, ROWS,[COLUMNS,COLS], ROWHEADERS,COLHEADERS, [OVERRIDE,FORCE],NOLABELS],@p); my($result,$checked); if (!$override && defined($self->param($name))) { $checked = $self->param($name); } else { $checked = $default; } my(@elements,@values); @values = $self->_set_values_and_labels($values,\$labels,$name); # If no check array is specified, check the first by default $checked = $values[0] unless defined($checked) && $checked ne ''; $name=$self->escapeHTML($name); my($other) = @other ? " @other" : ''; foreach (@values) { my($checkit) = $checked eq $_ ? qq/ checked="checked"/ : ''; my($break); if ($linebreak) { $break = $XHTML ? "<br />" : "<br>"; } else { $break = ''; } my($label)=''; unless (defined($nolabels) && $nolabels) { $label = $_; $label = $labels->{$_} if defined($labels) && defined($labels- +>{$_}); $label = $self->escapeHTML($label,1); } $_=$self->escapeHTML($_); push(@elements,$XHTML ? qq(<input type="radio" name="$name" value= +"$_"$checkit$other />${label}${break}) : qq/<input type="radio" name="$name" va +lue="$_"$checkit$other>${label}${break}/); } $self->register_parameter($name); return wantarray ? @elements : join(' ',@elements) unless defined($columns) || defined($rows); return _tableize($rows,$columns,$rowheaders,$colheaders,@elements) +; } END_OF_FUNC
    perl -MData::Dumper -MCGI=:all -e"print Dumper radio_group('IamGroup', +[qw/one othe r/],'one','linebreaks');" perl -MCGI=all -e"print textfield('other')"
    Now what I'm wondering is how is it that you didn't happen to stumble accross the CGI documentation, or even its guts?

    P.S. -- here's a few *secret* links, don't tell nobody ( CGI, How to RTFM, http://ovid.perlmonk.org, http://stein.cshl.org/, perlsec)

    update: Whaza?

    1) No the CGI documentation does not explicitly state how you can do what you want (you're doing some odd things, and it'd be crazy for the documentation to reflect that).

    2) Nooooo, If you don't know how to use certain functions, or they're not documented to your satisfaction, just crack open CGI.pm (and yeah, you could borrow, but that wasn't my point)

    3) Didn't mean to imply you should modify CGI.pm

    Yes, you missed my point completely (I guess I should've been more explicit, kinda like jeffa up there).

    I just wanted to point out to you, radio_group (which returns a list) and textfield, two CGI.pm functions, which *you* can use to solve your problem. You have to use your imagination as to how to do it (i ain't writing code like jeffa, ain't got time)

    Hopefully that clarifies it (if not, update your reply).
     

    Look ma', I'm on CPAN.


    ** The Third rule of perl club is a statement of fact: pod is sexy.

      I'm not sure I understand the point of your post. Are you saying that:

      • the CGI.pm documentation specifically describes how to do what I asked? If so, I need a better hint as to where. I had already read the links you referenced, as well as Lincoln Stein's book, but I couldn't find the answer to how to attach a text box to a radio button using CGI.pm. That's why I posted. :-)
        (I already know how to generate a radio group or a textbox with CGI.pm, and I could probably hack something together, but I don't think it would be very pretty.)

      • there are some undocumented features hidden in the CGI.pm code that I could exploit to meet my requirements? If so, I didn't see them.

      • rather than roll my own, I should modify the code from CGI.pm to do what I want? Since my code doesn't need to fit into Stein's fairly complex environment and doesn't need to be that generic, wouldn't that be kind of silly?

      Or it may be that I missed your point completely. I'm not trying to be ungrateful; I just need some clarification. :-(

      Thanks.
      Impossible Robot

Re: Creating HTML radio button group with text field
by impossiblerobot (Deacon) on May 05, 2002 at 15:07 UTC
    Here was my CGI.pm solution (with less relevant details stripped out):
    my @values = qw( a b c d ); my %labels = ( a => 'Friend', b => 'Magazine (please specify:)', c => 'Internet', d => 'Other', ); $labels{$_} = $cgi->escapeHTML($labels{$_}) for keys %labels; $labels{b} .= $cgi->textfield(-name => 'magname'); print $cgi->start_form(); $cgi->autoEscape(0); print $cgi->radio_group(-name => 'question', -values => \@values, -linebreak => 'true', -labels => \%labels); $cgi->autoEscape(1); print $cgi->endform;
    I didn't like having to turn off autoEscape() and explicitly escape the other entries, so I was looking for a cleaner solution -- but it looks like that's as good as it gets (with CGI.pm, at least).

    Thanks jeffa, podmaster.

    Impossible Robot

      This works for me however the only problem I get now is that whenever I click in the textfield, the focus always returns to the actual radiobutton so I can't actually type in the textfield

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://164082]
Approved by talexb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (11)
As of 2014-04-23 22:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (556 votes), past polls