source: text-formbuilder/trunk/lib/Text/FormBuilder.pm @ 70

Last change on this file since 70 was 70, checked in by peichman, 20 years ago

updated docs to match some changed features in the code
removed ':' from group field labels in the template

File size: 36.6 KB
Line 
1package Text::FormBuilder;
2
3use strict;
4use warnings;
5
6use base qw(Exporter Class::ParseText::Base);
7use vars qw($VERSION @EXPORT);
8
9$VERSION = '0.10';
10@EXPORT = qw(create_form);
11
12#$::RD_TRACE = 1;
13
14use Carp;
15use Text::FormBuilder::Parser;
16use CGI::FormBuilder;
17
18use Data::Dumper;
19$Data::Dumper::Terse = 1;           # don't dump $VARn names
20$Data::Dumper::Quotekeys = 0;       # don't quote simple string keys
21
22# the static default options passed to CGI::FormBuilder->new
23my %DEFAULT_OPTIONS = (
24    method => 'GET',
25    keepextras => 1,
26);
27
28# the built in CSS for the template
29my $DEFAULT_CSS = <<END;
30table { padding: 1em; }
31td table { padding: 0; } /* exclude the inner checkbox tables */
32#author, #footer { font-style: italic; }
33caption h2 { padding: .125em .5em; background: #ccc; text-align: left; }
34fieldset { margin: 1em 0; }
35legend { font-size: 1.25em; font-weight: bold; background: #ccc; padding: .125em .25em; border: 1px solid #666; }
36th { text-align: left; }
37th h3 { padding: .125em .5em; background: #eee; }
38th.label { font-weight: normal; text-align: right; vertical-align: top; }
39td ul { list-style: none; padding-left: 0; margin-left: 0; }
40.note { background: #eee; }
41.sublabel { color: #999; }
42.invalid { background: red; }
43END
44
45# default messages that can be localized
46my %DEFAULT_MESSAGES = (
47    text_author   => 'Created by %s',
48    text_madewith => 'Made with %s version %s',
49    text_required => '(Required fields are marked in <strong>bold</strong>.)',
50    text_invalid  => 'Missing or invalid value.',
51);
52
53my $DEFAULT_CHARSET = 'iso-8859-1';
54
55# options to clean up the code with Perl::Tidy
56my $TIDY_OPTIONS = '-nolq -ci=4 -ce';
57
58my $HTML_EXTS   = qr/\.html?$/;
59my $MODULE_EXTS = qr/\.pm$/;
60my $SCRIPT_EXTS = qr/\.(pl|cgi)$/;
61
62# superautomagical exported function
63sub create_form {
64    my ($source, $options, $destination) = @_;
65    my $parser = __PACKAGE__->parse($source);
66    $parser->build(%{ $options || {} });
67    if ($destination) {
68        if (ref $destination) {
69            croak '[' . (caller(0))[3] . "] Don't know what to do with a ref for $destination";
70            #TODO: what DO ref dests mean?
71        } else {
72            # write webpage, script, or module
73            if ($destination =~ $MODULE_EXTS) {
74                $parser->write_module($destination, 1);
75            } elsif ($destination =~ $SCRIPT_EXTS) {
76                $parser->write_script($destination, 1);
77            } else {
78                $parser->write($destination);
79            }
80        }
81    } else {
82        defined wantarray ? return $parser->form : $parser->write;
83    }
84}
85
86# subclass of Class::ParseText::Base
87sub init {
88    my $self = shift;
89    $self->{parser}         = Text::FormBuilder::Parser->new;
90    $self->{start_rule}     = 'form_spec';
91    $self->{ensure_newline} = 1;
92    return $self;
93}
94
95# this is where a lot of the magic happens
96sub build {
97    my ($self, %options) = @_;
98   
99    # our custom %options:
100    # form_only: use only the form part of the template
101    my $form_only = $options{form_only};
102   
103    # css, extra_css: allow for custom inline stylesheets
104    #   neat trick: css => '@import(my_external_stylesheet.css);'
105    #   will let you use an external stylesheet
106    #   CSS Hint: to get multiple sections to all line up their fields,
107    #   set a standard width for th.label
108    my $css;
109    $css = $options{css} || $DEFAULT_CSS;
110    $css .= $options{extra_css} if $options{extra_css};
111   
112    # messages
113    # code pulled (with modifications) from CGI::FormBuilder
114    if ($options{messages}) {
115        # if its a hashref, we'll just pass it on to CGI::FormBuilder
116       
117        if (my $ref = ref $options{messages}) {
118            # hashref pass on to CGI::FormBuilder
119            croak "[Text::FormBuilder] Argument to 'messages' option must be a filename or hashref" unless $ref eq 'HASH';
120            while (my ($key,$value) = each %DEFAULT_MESSAGES) {
121                $options{messages}{$key} ||= $DEFAULT_MESSAGES{$key};
122            }
123        } else {
124            # filename, just *warn* on missing, and use defaults
125            if (-f $options{messages} && -r _ && open(MESSAGES, "< $options{messages}")) {
126                $options{messages} = { %DEFAULT_MESSAGES };
127                while(<MESSAGES>) {
128                    next if /^\s*#/ || /^\s*$/;
129                    chomp;
130                    my($key,$value) = split ' ', $_, 2;
131                    ($options{messages}{$key} = $value) =~ s/\s+$//;
132                }
133                close MESSAGES;
134            } else {
135                carp '[' . (caller(0))[3] . "] Could not read messages file $options{messages}: $!";
136            }
137        }
138    } else {
139        $options{messages} = { %DEFAULT_MESSAGES };
140    }
141   
142    # character set
143    my $charset = $options{charset};
144   
145    # save the build options so they can be used from write_module
146    $self->{build_options} = { %options };
147   
148    # remove our custom options before we hand off to CGI::FormBuilder
149    delete $options{$_} foreach qw(form_only css extra_css charset);
150   
151    # expand groups
152    if (my %groups = %{ $self->{form_spec}{groups} || {} }) {       
153        for my $section (@{ $self->{form_spec}{sections} || [] }) {
154            foreach (grep { $$_[0] eq 'group' } @{ $$section{lines} }) {
155                $$_[1]{group} =~ s/^\%//;       # strip leading % from group var name
156               
157                if (exists $groups{$$_[1]{group}}) {
158                    my @fields; # fields in the group
159                    push @fields, { %$_ } foreach @{ $groups{$$_[1]{group}} };
160                    for my $field (@fields) {
161                        $$field{label} ||= ucfirst $$field{name};
162                        $$field{name} = "$$_[1]{name}_$$field{name}";               
163                    }
164                    $_ = [ 'group', { label => $$_[1]{label} || ucfirst(join(' ',split('_',$$_[1]{name}))), group => \@fields } ];
165                }
166            }
167        }
168    }
169   
170    # the actual fields that are given to CGI::FormBuilder
171    # make copies so that when we trim down the sections
172    # we don't lose the form field information
173    $self->{form_spec}{fields} = [];
174   
175    for my $section (@{ $self->{form_spec}{sections} || [] }) {
176        for my $line (@{ $$section{lines} }) {
177            if ($$line[0] eq 'group') {
178                push @{ $self->{form_spec}{fields} }, { %{$_} } foreach @{ $$line[1]{group} };
179            } elsif ($$line[0] eq 'field') {
180                push @{ $self->{form_spec}{fields} }, { %{$$line[1]} };
181            }
182        }
183    }
184   
185    # substitute in custom validation subs and pattern definitions for field validation
186    my %patterns = %{ $self->{form_spec}{patterns} || {} };
187    my %subs = %{ $self->{form_spec}{subs} || {} };
188   
189    foreach (@{ $self->{form_spec}{fields} }) {
190        if ($$_{validate}) {
191            if (exists $patterns{$$_{validate}}) {
192                $$_{validate} = $patterns{$$_{validate}};
193            # TODO: need the Data::Dumper code to work for this
194            # for now, we just warn that it doesn't work
195            } elsif (exists $subs{$$_{validate}}) {
196                warn '[' . (caller(0))[3] . "] validate coderefs don't work yet";
197                delete $$_{validate};
198##                 $$_{validate} = $subs{$$_{validate}};
199            }
200        }
201    }
202   
203    # get user-defined lists; can't make this conditional because
204    # we need to be able to fall back to CGI::FormBuilder's lists
205    # even if the user didn't define any
206    my %lists = %{ $self->{form_spec}{lists} || {} };
207   
208    # substitute in list names
209    foreach (@{ $self->{form_spec}{fields} }) {
210        next unless $$_{list};
211       
212        $$_{list} =~ s/^\@//;   # strip leading @ from list var name
213       
214        # a hack so we don't get screwy reference errors
215        if (exists $lists{$$_{list}}) {
216            my @list;
217            push @list, { %$_ } foreach @{ $lists{$$_{list}} };
218            $$_{options} = \@list;
219        } else {
220            # assume that the list name is a builtin
221            # and let it fall through to CGI::FormBuilder
222            $$_{options} = $$_{list};
223        }
224    } continue {
225        delete $$_{list};
226    }
227   
228    # special case single-value checkboxes
229    foreach (grep { $$_{type} && $$_{type} eq 'checkbox' } @{ $self->{form_spec}{fields} }) {
230        unless ($$_{options}) {
231            $$_{options} = [ { $$_{name} => $$_{label} || ucfirst join(' ',split(/_/,$$_{name})) } ];
232        }
233    }
234   
235    # use columns for displaying checkbox fields larger than 2 items
236    foreach (@{ $self->{form_spec}{fields} }) {
237        if (ref $$_{options} and @{ $$_{options} } >= 3) {
238            $$_{columns} = int(@{ $$_{options} } / 8) + 1;
239        }
240    }
241   
242    # remove extraneous undefined values
243    # also check for approriate version of CGI::FormBuilder
244    # for some advanced options
245    my $FB_version = CGI::FormBuilder->VERSION;
246    for my $field (@{ $self->{form_spec}{fields} }) {
247        defined $$field{$_} or delete $$field{$_} foreach keys %{ $field };
248       
249        unless ($FB_version >= '3.02') {
250            for (qw(growable other)) {
251                if ($$field{$_}) {
252                    warn '[' . (caller(0))[3] . "] '$_' fields not supported by FB $FB_version (requires 3.02)";
253                    delete $$field{$_};
254                }
255            }
256        }
257    }
258   
259    # assign the field names to the sections
260    foreach (@{ $self->{form_spec}{sections} }) {
261        for my $line (@{ $$_{lines} }) {
262            if ($$line[0] eq 'field') {
263                $$line[1] = $$line[1]{name};
264            }
265        }
266    }
267   
268    # gather together all of the form options
269    $self->{form_options} = {
270        %DEFAULT_OPTIONS,
271        # need to explicity set the fields so that simple text fields get picked up
272        fields   => [ map { $$_{name} } @{ $self->{form_spec}{fields} } ],
273        required => [ map { $$_{name} } grep { $$_{required} } @{ $self->{form_spec}{fields} } ],
274        title => $self->{form_spec}{title},
275        text  => $self->{form_spec}{description},
276        template => {
277            type => 'Text',
278            engine => {
279                TYPE       => 'STRING',
280                SOURCE     => $form_only ? $self->_form_template : $self->_template($css, $charset),
281                DELIMITERS => [ qw(<% %>) ],
282            },
283            data => {
284                sections    => $self->{form_spec}{sections},
285                author      => $self->{form_spec}{author},
286                description => $self->{form_spec}{description},
287            },
288        },
289        %options,
290    };
291   
292    # create the form object
293    $self->{form} = CGI::FormBuilder->new(%{ $self->{form_options} });
294   
295    # ...and set up its fields
296    $self->{form}->field(%{ $_ }) foreach @{ $self->{form_spec}{fields} };
297   
298    # mark structures as built
299    $self->{built} = 1;
300   
301    return $self;
302}
303
304sub write {
305    my ($self, $outfile) = @_;
306   
307    # automatically call build if needed to
308    # allow the new->parse->write shortcut
309    $self->build unless $self->{built};
310   
311    if ($outfile) {
312        open FORM, "> $outfile";
313        print FORM $self->form->render;
314        close FORM;
315    } else {
316        print $self->form->render;
317    }
318}
319
320# dump the form options as eval-able code
321sub _form_options_code {
322    my $self = shift;
323    my $d = Data::Dumper->new([ $self->{form_options} ], [ '*options' ]);
324    return keys %{ $self->{form_options} } > 0 ? $d->Dump : '';   
325}
326# dump the field setup subs as eval-able code
327# pass in the variable name of the form object
328# (defaults to '$form')
329# TODO: revise this code to use the new 'fieldopts'
330# option to the FB constructor (requires FB 3.02)
331sub _field_setup_code {
332    my $self = shift;
333    my $object_name = shift || '$form';
334    return join(
335        "\n", 
336        map { $object_name . '->field' . Data::Dumper->Dump([$_],['*field']) . ';' } @{ $self->{form_spec}{fields} }
337    );
338}   
339
340sub write_module {
341    my ($self, $package, $use_tidy) = @_;
342
343    croak '[' . (caller(0))[3] . '] Expecting a package name' unless $package;
344   
345    # remove a trailing .pm
346    $package =~ s/\.pm$//;
347##     warn  "[Text::FromBuilder::write_module] Removed extra '.pm' from package name\n" if $package =~ s/\.pm$//;
348   
349    my $form_options = $self->_form_options_code;
350    my $field_setup = $self->_field_setup_code('$self');
351   
352    # old style of module
353    # TODO: how to keep this (as deprecated method)
354    my $old_module = <<END;
355package $package;
356use strict;
357use warnings;
358
359use CGI::FormBuilder;
360
361sub get_form {
362    my \$q = shift;
363
364    my \$self = CGI::FormBuilder->new(
365        $form_options,
366        \@_,
367    );
368   
369    $field_setup
370   
371    return \$self;
372}
373
374# module return
3751;
376END
377
378    # new style of module
379    my $module = <<END;
380package $package;
381use strict;
382use warnings;
383
384use base qw(CGI::FormBuilder);
385
386sub new {
387    my \$invocant = shift;
388    my \$class = ref \$invocant || \$invocant;
389   
390    my \$self = CGI::FormBuilder->new(
391        $form_options,
392        \@_,
393    );
394   
395    $field_setup
396   
397    # re-bless into this class
398    bless \$self, \$class;
399}
400
401# module return
4021;
403END
404    _write_output_file($module, (split(/::/, $package))[-1] . '.pm', $use_tidy);
405    return $self;
406}
407
408sub write_script {
409    my ($self, $script_name, $use_tidy) = @_;
410
411    croak '[' . (caller(0))[3] . '] Expecting a script name' unless $script_name;
412   
413    my $form_options = $self->_form_options_code;
414    my $field_setup = $self->_field_setup_code('$form');
415
416    my $script = <<END;
417#!/usr/bin/perl
418use strict;
419use warnings;
420
421use CGI::FormBuilder;
422
423my \$form = CGI::FormBuilder->new(
424    $form_options
425);
426
427$field_setup
428   
429unless (\$form->submitted && \$form->validate) {
430    print \$form->render;
431} else {
432    # do something with the entered data
433}
434END
435   
436    _write_output_file($script, $script_name, $use_tidy);   
437    return $self;
438}
439
440sub _write_output_file {
441    my ($source_code, $outfile, $use_tidy) = @_;
442    if ($use_tidy) {
443        # clean up the generated code, if asked
444        eval 'use Perl::Tidy';
445        unless ($@) {
446            Perl::Tidy::perltidy(source => \$source_code, destination => $outfile, argv => $TIDY_OPTIONS);
447        } else {
448            carp '[' . (caller(0))[3] . "] Can't tidy the code: $@" if $@;
449            # fallback to just writing it as-is
450            open OUT, "> $outfile" or die $!;
451            print OUT $source_code;
452            close OUT;
453        }
454    } else {
455        # otherwise, just print as is
456        open OUT, "> $outfile" or die $!;
457        print OUT $source_code;
458        close OUT;
459    }
460}
461
462
463sub form {
464    my $self = shift;
465   
466    # automatically call build if needed to
467    # allow the new->parse->write shortcut
468    $self->build unless $self->{built};
469
470    return $self->{form};
471}
472
473sub _form_template {
474    my $self = shift;
475    my $msg_required = $self->{build_options}{messages}{text_required};
476    my $msg_invalid = $self->{build_options}{messages}{text_invalid};
477    return q{<% $description ? qq[<p id="description">$description</p>] : '' %>
478<% (grep { $_->{required} } @fields) ? qq[<p id="instructions">} . $msg_required . q{</p>] : '' %>
479<% $start %>
480<%
481    # drop in the hidden fields here
482    $OUT = join("\n", map { $$_{field} } grep { $$_{type} eq 'hidden' } @fields);
483%>} .
484q[
485<%
486    SECTION: while (my $section = shift @sections) {
487        $OUT .= qq[<fieldset>\n];
488        $OUT .= qq[  <legend>$$section{head}</legend>] if $$section{head};
489        $OUT .= qq[<table id="] . ($$section{id} || '_default') . qq[">\n];
490        #$OUT .= qq[  <caption><h2 class="sectionhead">$$section{head}</h2></caption>] if $$section{head};
491        TABLE_LINE: for my $line (@{ $$section{lines} }) {
492            if ($$line[0] eq 'head') {
493                $OUT .= qq[  <tr><th class="subhead" colspan="2"><h3>$$line[1]</h3></th></tr>\n]
494            } elsif ($$line[0] eq 'note') {
495                $OUT .= qq[  <tr><td class="note" colspan="2">$$line[1]</td></tr>\n]
496            } elsif ($$line[0] eq 'field') {
497                local $_ = $field{$$line[1]};
498               
499                # skip hidden fields in the table
500                next TABLE_LINE if $$_{type} eq 'hidden';
501               
502                $OUT .= $$_{invalid} ? qq[  <tr class="invalid">] : qq[  <tr>];
503               
504                # special case single value checkboxes
505                if ($$_{type} eq 'checkbox' && @{ $$_{options} } == 1) {
506                    $OUT .= qq[<th></th>];
507                } else {
508                    $OUT .= '<th class="label">' . ($$_{required} ? qq[<strong class="required">$$_{label}</strong>] : "$$_{label}") . '</th>';
509                }
510               
511                # mark invalid fields
512                if ($$_{invalid}) {
513                    $OUT .= "<td>$$_{field} $$_{comment} ] . $msg_invalid . q[</td>";
514                } else {
515                    $OUT .= qq[<td>$$_{field} $$_{comment}</td>];
516                }
517               
518                $OUT .= qq[</tr>\n];
519               
520            } elsif ($$line[0] eq 'group') {
521                my @group_fields = map { $field{$_} } map { $$_{name} } @{ $$line[1]{group} };
522                $OUT .= (grep { $$_{invalid} } @group_fields) ? qq[  <tr class="invalid">\n] : qq[  <tr>\n];
523               
524                $OUT .= '    <th class="label">';
525                $OUT .= (grep { $$_{required} } @group_fields) ? qq[<strong class="required">$$line[1]{label}</strong>] : "$$line[1]{label}";
526                $OUT .= qq[</th>\n];
527               
528                $OUT .= qq[    <td><span class="fieldgroup">];
529                $OUT .= join(' ', map { qq[<small class="sublabel">$$_{label}</small> $$_{field} $$_{comment}] } @group_fields);
530                #TODO: allow comments on field groups
531                $OUT .= " ] . $msg_invalid . q[" if grep { $$_{invalid} } @group_fields;
532               
533                $OUT .= qq[    </span></td>\n];
534                $OUT .= qq[  </tr>\n];
535            }   
536        }
537        # close the table if there are sections remaining
538        # but leave the last one open for the submit button
539        if (@sections) {
540            $OUT .= qq[</table>\n];
541            $OUT .= qq[</fieldset>\n];
542        }
543    }
544%>
545  <tr><td colspan="2"><hr /></td></tr>
546  <tr><th></th><td style="padding-top: 1em;"><% $submit %></td></tr>
547</table>
548</fieldset>
549<% $end %>
550];
551}
552
553# usage: $self->_pre_template($css, $charset)
554sub _pre_template {
555    my $self = shift;
556    my $css = shift || $DEFAULT_CSS;
557    my $charset = shift || $DEFAULT_CHARSET;
558    my $msg_author = 'sprintf("' . quotemeta($self->{build_options}{messages}{text_author}) . '", $author)';
559    return 
560q[<html>
561<head>
562  <meta http-equiv="Content-Type" content="text/html; charset=] . $charset . q[" />
563  <title><% $title %><% $author ? ' - ' . ucfirst $author : '' %></title>
564  <style type="text/css">
565] . $css . q[  </style>
566  <% $jshead %>
567</head>
568<body>
569
570<h1><% $title %></h1>
571<% $author ? qq[<p id="author">] . ] . $msg_author . q{ . q[</p>] : '' %>
572};
573}
574
575sub _post_template {
576    my $self = shift;
577    my $msg_madewith = 'sprintf("' . quotemeta($self->{build_options}{messages}{text_madewith}) .
578        '", q[<a href="http://formbuilder.org/">CGI::FormBuilder</a>], CGI::FormBuilder->VERSION)';
579   
580    return qq[<hr />
581<div id="footer">
582  <p id="creator"><% $msg_madewith %></p>
583</div>
584</body>
585</html>
586];
587}
588
589# usage: $self->_template($css, $charset)
590sub _template {
591    my $self = shift;
592    return $self->_pre_template(@_) . $self->_form_template . $self->_post_template;
593}
594
595sub dump { 
596    eval "use YAML;";
597    unless ($@) {
598        print YAML::Dump(shift->{form_spec});
599    } else {
600        warn '[' . (caller(0))[3] . "] Can't dump form spec structure using YAML: $@";
601    }
602}
603
604
605# module return
6061;
607
608=head1 NAME
609
610Text::FormBuilder - Create CGI::FormBuilder objects from simple text descriptions
611
612=head1 SYNOPSIS
613
614    use Text::FormBuilder;
615   
616    my $parser = Text::FormBuilder->new;
617    $parser->parse($src_file);
618   
619    # returns a new CGI::FormBuilder object with
620    # the fields from the input form spec
621    my $form = $parser->form;
622   
623    # write a My::Form module to Form.pm
624    $parser->write_module('My::Form');
625
626=head1 REQUIRES
627
628L<Parse::RecDescent>,
629L<CGI::FormBuilder>,
630L<Text::Template>,
631L<Class::Base>
632
633=head1 DESCRIPTION
634
635This module is intended to extend the idea of making it easy to create
636web forms by allowing you to describe them with a simple langauge. These
637I<formspecs> are then passed through this module's parser and converted
638into L<CGI::FormBuilder> objects that you can easily use in your CGI
639scripts. In addition, this module can generate code for standalone modules
640which allow you to separate your form design from your script code.
641
642A simple formspec looks like this:
643
644    name//VALUE
645    email//EMAIL
646    langauge:select{English,Spanish,French,German}
647    moreinfo|Send me more information:checkbox
648    interests:checkbox{Perl,karate,bass guitar}
649
650This will produce a required C<name> test field, a required C<email> text
651field that must look like an email address, an optional select dropdown
652field C<langauge> with the choices English, Spanish, French, and German,
653an optional C<moreinfo> checkbox labeled ``Send me more information'', and
654finally a set of checkboxes named C<interests> with the choices Perl,
655karate, and bass guitar.
656
657=head1 METHODS
658
659=head2 new
660
661    my $parser = Text::FormBuilder->new;
662
663=head2 parse
664
665    # parse a file (regular scalar)
666    $parser->parse($filename);
667   
668    # or pass a scalar ref for parse a literal string
669    $parser->parse(\$string);
670   
671    # or an array ref to parse lines
672    $parser->parse(\@lines);
673
674Parse the file or string. Returns the parser object. This method,
675along with all of its C<parse_*> siblings, may be called as a class
676method to construct a new object.
677
678=head2 parse_file
679
680    $parser->parse_file($src_file);
681   
682    # or as a class method
683    my $parser = Text::FormBuilder->parse($src_file);
684
685=head2 parse_text
686
687    $parser->parse_text($src);
688
689Parse the given C<$src> text. Returns the parser object.
690
691=head2 parse_array
692
693    $parser->parse_array(@lines);
694
695Concatenates and parses C<@lines>. Returns the parser object.
696
697=head2 build
698
699    $parser->build(%options);
700
701Builds the CGI::FormBuilder object. Options directly used by C<build> are:
702
703=over
704
705=item C<form_only>
706
707Only uses the form portion of the template, and omits the surrounding html,
708title, author, and the standard footer. This does, however, include the
709description as specified with the C<!description> directive.
710
711=item C<css>, C<extra_css>
712
713These options allow you to tell Text::FormBuilder to use different
714CSS styles for the built in template. A value given a C<css> will
715replace the existing CSS, and a value given as C<extra_css> will be
716appended to the CSS. If both options are given, then the CSS that is
717used will be C<css> concatenated with C<extra_css>.
718
719If you want to use an external stylesheet, a quick way to get this is
720to set the C<css> parameter to import your file:
721
722    css => '@import(my_external_stylesheet.css);'
723
724=item C<messages>
725
726This works the same way as the C<messages> parameter to
727C<< CGI::FormBuilder->new >>; you can provide either a hashref of messages
728or a filename.
729
730The default messages used by Text::FormBuilder are:
731
732    text_author       Created by %s
733    text_madewith     Made with %s version %s
734    text_required     (Required fields are marked in <strong>bold</strong>.)
735    text_invalid      Missing or invalid value.
736
737Any messages you set here get passed on to CGI::FormBuilder, which means
738that you should be able to put all of your customization messages in one
739big file.
740
741=item C<charset>
742
743Sets the character encoding for the generated page. The default is ISO-8859-1.
744
745=back
746
747All other options given to C<build> are passed on verbatim to the
748L<CGI::FormBuilder> constructor. Any options given here override the
749defaults that this module uses.
750
751The C<form>, C<write>, and C<write_module> methods will all call
752C<build> with no options for you if you do not do so explicitly.
753This allows you to say things like this:
754
755    my $form = Text::FormBuilder->new->parse('formspec.txt')->form;
756
757However, if you need to specify options to C<build>, you must call it
758explictly after C<parse>.
759
760=head2 form
761
762    my $form = $parser->form;
763
764Returns the L<CGI::FormBuilder> object. Remember that you can modify
765this object directly, in order to (for example) dynamically populate
766dropdown lists or change input types at runtime.
767
768=head2 write
769
770    $parser->write($out_file);
771    # or just print to STDOUT
772    $parser->write;
773
774Calls C<render> on the FormBuilder form, and either writes the resulting
775HTML to a file, or to STDOUT if no filename is given.
776
777=head2 write_module
778
779I<B<Note:> The code output from the C<write_*> methods may be in flux for
780the next few versions, as I coordinate with the B<FormBuilder> project.>
781
782    $parser->write_module($package, $use_tidy);
783
784Takes a package name, and writes out a new module that can be used by your
785CGI script to render the form. This way, you only need CGI::FormBuilder on
786your server, and you don't have to parse the form spec each time you want
787to display your form. The generated module has one function (not exported)
788called C<get_form>, that takes a CGI object as its only argument, and returns
789a CGI::FormBuilder object.
790
791First, you parse the formspec and write the module, which you can do as a one-liner:
792
793    $ perl -MText::FormBuilder -e"Text::FormBuilder->parse('formspec.txt')->write_module('My::Form')"
794
795And then, in your CGI script, use the new module:
796
797    #!/usr/bin/perl -w
798    use strict;
799   
800    use CGI;
801    use My::Form;
802   
803    my $q = CGI->new;
804    my $form = My::Form::get_form($q);
805   
806    # do the standard CGI::FormBuilder stuff
807    if ($form->submitted && $form->validate) {
808        # process results
809    } else {
810        print $q->header;
811        print $form->render;
812    }
813
814If you pass a true value as the second argument to C<write_module>, the parser
815will run L<Perl::Tidy> on the generated code before writing the module file.
816
817    # write tidier code
818    $parser->write_module('My::Form', 1);
819
820=head2 write_script
821
822    $parser->write_script($filename, $use_tidy);
823
824If you don't need the reuseability of a separate module, you can have
825Text::FormBuilder write the form object to a script for you, along with
826the simplest framework for using it, to which you can add your actual
827form processing code.
828
829The generated script looks like this:
830
831    #!/usr/bin/perl
832    use strict;
833    use warnings;
834   
835    use CGI;
836    use CGI::FormBuilder;
837   
838    my $q = CGI->new;
839   
840    my $form = CGI::FormBuilder->new(
841        params => $q,
842        # ... lots of other stuff to set up the form ...
843    );
844   
845    $form->field( name => 'month' );
846    $form->field( name => 'day' );
847   
848    unless ( $form->submitted && $form->validate ) {
849        print $form->render;
850    } else {
851        # do something with the entered data ...
852        # this is where your form processing code should go
853    }
854
855Like C<write_module>, you can optionally pass a true value as the second
856argument to have Perl::Tidy make the generated code look nicer.
857
858=head2 dump
859
860Uses L<YAML> to print out a human-readable representation of the parsed
861form spec.
862
863=head1 EXPORTS
864
865There is one exported function, C<create_form>, that is intended to ``do the
866right thing'' in simple cases.
867
868=head2 create_form
869
870    # get a CGI::FormBuilder object
871    my $form = create_form($source, $options, $destination);
872   
873    # or just write the form immediately
874    create_form($source, $options, $destination);
875
876C<$source> accepts any of the types of arguments that C<parse> does. C<$options>
877is a hashref of options that should be passed to C<build>. Finally, C<$destination>
878is a simple scalar that determines where and what type of output C<create_form>
879should generate.
880
881    /\.pm$/             ->write_module($destination)
882    /\.(cgi|pl)$/       ->write_script($destination)
883    everything else     ->write($destination)
884
885For anything more than simple, one-off cases, you are usually better off using the
886object-oriented interface, since that gives you more control over things.
887
888=head1 DEFAULTS
889
890These are the default settings that are passed to C<< CGI::FormBuilder->new >>:
891
892    method => 'GET'
893    keepextras => 1
894
895Any of these can be overriden by the C<build> method:
896
897    # use POST instead
898    $parser->build(method => 'POST')->write;
899
900=head1 LANGUAGE
901
902    field_name[size]|descriptive label[hint]:type=default{option1[display string],...}//validate
903   
904    !title ...
905   
906    !author ...
907   
908    !description {
909        ...
910    }
911   
912    !pattern NAME /regular expression/
913   
914    !list NAME {
915        option1[display string],
916        option2[display string],
917        ...
918    }
919   
920    !group NAME {
921        field1
922        field2
923        ...
924    }
925   
926    !section id heading
927   
928    !head ...
929   
930    !note {
931        ...
932    }
933
934=head2 Directives
935
936=over
937
938=item C<!pattern>
939
940Defines a validation pattern.
941
942=item C<!list>
943
944Defines a list for use in a C<radio>, C<checkbox>, or C<select> field.
945
946=item C<!group>
947
948Define a named group of fields that are displayed all on one line. Use with
949the C<!field> directive.
950
951=item C<!field>
952
953Include a named instance of a group defined with C<!group>.
954
955=item C<!title>
956
957Title of the form.
958
959=item C<!author>
960
961Author of the form.
962
963=item C<!description>
964
965A brief description of the form. Suitable for special instructions on how to
966fill out the form.
967
968=item C<!section>
969
970Starts a new section. Each section has its own heading and id, which are
971written by default into spearate tables.
972
973=item C<!head>
974
975Inserts a heading between two fields. There can only be one heading between
976any two fields; the parser will warn you if you try to put two headings right
977next to each other.
978
979=item C<!note>
980
981A text note that can be inserted as a row in the form. This is useful for
982special instructions at specific points in a long form.
983
984=back
985
986=head2 Fields
987
988First, a note about multiword strings in the fields. Anywhere where it says
989that you may use a multiword string, this means that you can do one of two
990things. For strings that consist solely of alphanumeric characters (i.e.
991C<\w+>) and spaces, the string will be recognized as is:
992
993    field_1|A longer label
994
995If you want to include non-alphanumerics (e.g. punctuation), you must
996single-quote the string:
997
998    field_2|'Dept./Org.'
999
1000To include a literal single-quote in a single-quoted string, escape it with
1001a backslash:
1002
1003    field_3|'\'Official\' title'
1004
1005Now, back to the beginning. Form fields are each described on a single line.
1006The simplest field is just a name (which cannot contain any whitespace):
1007
1008    color
1009
1010This yields a form with one text input field of the default size named `color'.
1011The generated label for this field would be ``Color''. To add a longer or more\
1012descriptive label, use:
1013
1014    color|Favorite color
1015
1016The descriptive label can be a multiword string, as described above. So if you
1017want punctuation in the label, you should single quote it:
1018
1019    color|'Fav. color'
1020
1021To use a different input type:
1022
1023    color|Favorite color:select{red,blue,green}
1024
1025Recognized input types are the same as those used by CGI::FormBuilder:
1026
1027    text        # the default
1028    textarea
1029    password
1030    file
1031    checkbox
1032    radio
1033    select
1034    hidden
1035    static
1036
1037To change the size of the input field, add a bracketed subscript after the
1038field name (but before the descriptive label):
1039
1040    # for a single line field, sets size="40"
1041    title[40]:text
1042   
1043    # for a multiline field, sets rows="4" and cols="30"
1044    description[4,30]:textarea
1045
1046To also set the C<maxlength> attribute for text fields, add a C<!> after
1047the size:
1048
1049    # ensure that all titles entered are 40 characters or less
1050    title[40!]:text
1051
1052This currently only works for single line text fields.
1053
1054To create a growable field, add a C<*> after the name (and size, if
1055given). Growable fields have a button that allows the user to add a
1056copy of the field input. Currently, this only works for C<text> and
1057C<file> fields, and you must have L<CGI::FormBuilder> 3.02 or higher.
1058Growable fields also require JavaScript to function correctly.
1059
1060    # you can have as many people as you like
1061    person*:text
1062
1063For the input types that can have options (C<select>, C<radio>, and
1064C<checkbox>), here's how you do it:
1065
1066    color|Favorite color:select{red,blue,green}
1067
1068Values are in a comma-separated list of single words or multiword strings
1069inside curly braces. Whitespace between values is irrelevant.
1070
1071To add more descriptive display text to a value in a list, add a square-bracketed
1072``subscript,'' as in:
1073
1074    ...:select{red[Scarlet],blue[Azure],green[Olive Drab]}
1075
1076If you have a list of options that is too long to fit comfortably on one line,
1077you should use the C<!list> directive:
1078
1079    !list MONTHS {
1080        1[January],
1081        2[February],
1082        3[March],
1083        # and so on...
1084    }
1085   
1086    month:select@MONTHS
1087
1088If you want to have a single checkbox (e.g. for a field that says ``I want to
1089recieve more information''), you can just specify the type as checkbox without
1090supplying any options:
1091
1092    moreinfo|I want to recieve more information:checkbox
1093
1094In this case, the label ``I want to recieve more information'' will be
1095printed to the right of the checkbox.
1096
1097You can also supply a default value to the field. To get a default value of
1098C<green> for the color field:
1099
1100    color|Favorite color:select=green{red,blue,green}
1101
1102Default values can also be either single words or multiword strings.
1103
1104To validate a field, include a validation type at the end of the field line:
1105
1106    email|Email address//EMAIL
1107
1108Valid validation types include any of the builtin defaults from L<CGI::FormBuilder>,
1109or the name of a pattern that you define with the C<!pattern> directive elsewhere
1110in your form spec:
1111
1112    !pattern DAY /^([1-3][0-9])|[1-9]$/
1113   
1114    last_day//DAY
1115
1116If you just want a required value, use the builtin validation type C<VALUE>:
1117
1118    title//VALUE
1119
1120By default, adding a validation type to a field makes that field required. To
1121change this, add a C<?> to the end of the validation type:
1122
1123    contact//EMAIL?
1124
1125In this case, you would get a C<contact> field that was optional, but if it
1126were filled in, would have to validate as an C<EMAIL>.
1127
1128=head2 Field Groups
1129
1130You can define groups of fields using the C<!group> directive:
1131
1132    !group DATE {
1133        month:select@MONTHS//INT
1134        day[2]//INT
1135        year[4]//INT
1136    }
1137
1138You can then include instances of this group using the C<!field> directive:
1139
1140    !field %DATE birthday
1141
1142This will create a line in the form labeled ``Birthday'' which contains
1143a month dropdown, and day and year text entry fields. The actual input field
1144names are formed by concatenating the C<!field> name (e.g. C<birthday>) with
1145the name of the subfield defined in the group (e.g. C<month>, C<day>, C<year>).
1146Thus in this example, you would end up with the form fields C<birthday_month>,
1147C<birthday_day>, and C<birthday_year>.
1148
1149You can also use groups in normal field lines:
1150   
1151    birthday|Your birthday:DATE
1152
1153The only (currently) supported pieces of a fieldspec that may be used with a
1154group in this notation are name and label.
1155
1156=head2 Comments
1157
1158    # comment ...
1159
1160Any line beginning with a C<#> is considered a comment.
1161
1162=head1 TODO
1163
1164=head2 Documentation/Tests
1165
1166Document use of the parser as a standalone module
1167
1168Better tests!
1169
1170=head2 Language/Parser
1171
1172Allow renaming of the submit button; allow renaming and inclusion of a
1173reset button
1174
1175Allow comments on group fields (rendered after the all the fields)
1176
1177Pieces that wouldn't make sense in a group field: size, row/col, options,
1178validate. These should cause C<build> to emit a warning before ignoring them.
1179
1180C<!include> directive to include external formspec files
1181
1182=head2 Code generation/Templates
1183
1184Alternative format using C<< <fieldset> >> tags instead of C<< <h2> >>
1185section headers
1186
1187Make the generated modules into subclasses of CGI::FormBuilder
1188
1189Revise the generated form constructing code to use the C<fieldopts>
1190option to C<< FB->new >>; will require FB 3.02 to run.
1191
1192Better integration with L<CGI::FormBuilder>'s templating system
1193
1194Allow for custom wrappers around the C<form_template>
1195
1196Maybe use HTML::Template instead of Text::Template for the built in template
1197(since CGI::FormBuilder users may be more likely to already have HTML::Template)
1198
1199=head1 BUGS
1200
1201Creating two $parsers in the same script causes the second one to get the data
1202from the first one.
1203
1204I'm sure there are more in there, I just haven't tripped over any new ones lately. :-)
1205
1206Suggestions on how to improve the (currently tiny) test suite would be appreciated.
1207
1208=head1 SEE ALSO
1209
1210L<http://textformbuilder.berlios.de>
1211
1212L<CGI::FormBuilder>, L<http://formbuilder.org>
1213
1214=head1 THANKS
1215
1216Thanks to eszpee for pointing out some bugs in the default value parsing,
1217as well as some suggestions for i18n/l10n and splitting up long forms into
1218sections.
1219
1220And of course, to Nathan Wiger, for giving use CGI::FormBuilder in the
1221first place. Thanks Nate!
1222
1223=head1 AUTHOR
1224
1225Peter Eichman C<< <peichman@cpan.org> >>
1226
1227=head1 COPYRIGHT AND LICENSE
1228
1229Copyright E<copy>2004-2005 by Peter Eichman.
1230
1231This program is free software; you can redistribute it and/or
1232modify it under the same terms as Perl itself.
1233
1234=cut
Note: See TracBrowser for help on using the repository browser.