Changeset 29 in text-formbuilder for trunk


Ignore:
Timestamp:
11/17/04 10:03:41 (20 years ago)
Author:
peter
Message:

added !section directive

Location:
trunk/lib/Text
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/Text/FormBuilder.pm

    r28 r29  
    8787    # expand groups 
    8888    my %groups = %{ $self->{form_spec}{groups} || {} }; 
    89     foreach (grep { $$_[0] eq 'group' } @{ $self->{form_spec}{lines} || [] }) { 
    90         $$_[1]{group} =~ s/^\%//;       # strip leading % from group var name 
    91          
    92         if (exists $groups{$$_[1]{group}}) { 
    93             my @fields; # fields in the group 
    94             push @fields, { %$_ } foreach @{ $groups{$$_[1]{group}} }; 
    95             for my $field (@fields) { 
    96                 $$field{label} ||= ucfirst $$field{name}; 
    97                 $$field{name} = "$$_[1]{name}_$$field{name}";                 
     89     
     90    for my $section (@{ $self->{form_spec}{sections} || [] }) { 
     91##         foreach (grep { $$_[0] eq 'group' } @{ $self->{form_spec}{lines} || [] }) { 
     92        foreach (grep { $$_[0] eq 'group' } @{ $$section{lines} }) { 
     93            $$_[1]{group} =~ s/^\%//;       # strip leading % from group var name 
     94             
     95            if (exists $groups{$$_[1]{group}}) { 
     96                my @fields; # fields in the group 
     97                push @fields, { %$_ } foreach @{ $groups{$$_[1]{group}} }; 
     98                for my $field (@fields) { 
     99                    $$field{label} ||= ucfirst $$field{name}; 
     100                    $$field{name} = "$$_[1]{name}_$$field{name}";                 
     101                } 
     102                $_ = [ 'group', { label => $$_[1]{label} || ucfirst(join(' ',split('_',$$_[1]{name}))), group => \@fields } ]; 
    98103            } 
    99             $_ = [ 'group', { label => $$_[1]{label} || ucfirst(join(' ',split('_',$$_[1]{name}))), group => \@fields } ]; 
    100104        } 
    101105    } 
    102106     
    103107    $self->{form_spec}{fields} = []; 
    104     for my $line (@{ $self->{form_spec}{lines} || [] }) { 
    105         if ($$line[0] eq 'group') { 
    106             push @{ $self->{form_spec}{fields} }, $_ foreach @{ $$line[1]{group} }; 
    107         } elsif ($$line[0] eq 'field') { 
    108             push @{ $self->{form_spec}{fields} }, $$line[1]; 
     108     
     109    for my $section (@{ $self->{form_spec}{sections} || [] }) { 
     110        #for my $line (@{ $self->{form_spec}{lines} || [] }) { 
     111        for my $line (@{ $$section{lines} }) { 
     112            if ($$line[0] eq 'group') { 
     113                push @{ $self->{form_spec}{fields} }, $_ foreach @{ $$line[1]{group} }; 
     114            } elsif ($$line[0] eq 'field') { 
     115                push @{ $self->{form_spec}{fields} }, $$line[1]; 
     116            } 
    109117        } 
    110118    } 
    111      
    112119     
    113120    # substitute in list names 
     
    149156    $$_{required} or delete $$_{required} foreach @{ $self->{form_spec}{fields} }; 
    150157 
    151      
     158    # need to explicity set the fields so that simple text fields get picked up 
    152159    $self->{form} = CGI::FormBuilder->new( 
    153160        %DEFAULT_OPTIONS, 
     161        fields   => [ map { $$_{name} } @{ $self->{form_spec}{fields} } ], 
    154162        required => [ map { $$_{name} } grep { $$_{required} } @{ $self->{form_spec}{fields} } ], 
    155163        title => $self->{form_spec}{title}, 
     
    163171            }, 
    164172            data => { 
    165                 lines       => $self->{form_spec}{lines}, 
     173                sections    => $self->{form_spec}{sections}, 
    166174                author      => $self->{form_spec}{author}, 
    167175                description => $self->{form_spec}{description}, 
     
    214222        title => $self->{form_spec}{title}, 
    215223        text  => $self->{form_spec}{description}, 
     224        fields   => [ map { $$_{name} } @{ $self->{form_spec}{fields} } ], 
    216225        required => [ map { $$_{name} } grep { $$_{required} } @{ $self->{form_spec}{fields} } ], 
    217226        template => { 
     
    223232            }, 
    224233            data => { 
    225                 lines       => $self->{form_spec}{lines}, 
     234                sections    => $self->{form_spec}{sections}, 
    226235                author      => $self->{form_spec}{author}, 
    227236                description => $self->{form_spec}{description}, 
     
    299308%> 
    300309 
    301 <table> 
    302  
    303 <% TABLE_LINE: for my $line (@lines) { 
    304  
    305     if ($$line[0] eq 'head') { 
    306         $OUT .= qq[  <tr><th class="sectionhead" colspan="2"><h2>$$line[1]</h2></th></tr>\n] 
    307     } elsif ($$line[0] eq 'field') { 
    308         #TODO: we only need the field names, not the full field spec in the lines strucutre 
    309         local $_ = $field{$$line[1]{name}}; 
    310         # skip hidden fields in the table 
    311         next TABLE_LINE if $$_{type} eq 'hidden'; 
    312          
    313         $OUT .= $$_{invalid} ? qq[  <tr class="invalid">] : qq[  <tr>]; 
    314         $OUT .= '<th class="label">' . ($$_{required} ? qq[<strong class="required">$$_{label}:</strong>] : "$$_{label}:") . '</th>'; 
    315         if ($$_{invalid}) { 
    316             $OUT .= qq[<td>$$_{field} $$_{comment} Missing or invalid value.</td></tr>\n]; 
    317         } else { 
    318             $OUT .= qq[<td>$$_{field} $$_{comment}</td></tr>\n]; 
     310<% 
     311    SECTION: while (my $section = shift @sections) { 
     312        $OUT .= qq[<table id="$$section{id}">\n]; 
     313        $OUT .= qq[  <caption><h2>$$section{head}</h2></caption>] if $$section{head}; 
     314        TABLE_LINE: for my $line (@{ $$section{lines} }) { 
     315            if ($$line[0] eq 'head') { 
     316                $OUT .= qq[  <tr><th class="sectionhead" colspan="2"><h3>$$line[1]</h3></th></tr>\n] 
     317            } elsif ($$line[0] eq 'field') { 
     318                #TODO: we only need the field names, not the full field spec in the lines strucutre 
     319                local $_ = $field{$$line[1]{name}}; 
     320                # skip hidden fields in the table 
     321                next TABLE_LINE if $$_{type} eq 'hidden'; 
     322                 
     323                $OUT .= $$_{invalid} ? qq[  <tr class="invalid">] : qq[  <tr>]; 
     324                $OUT .= '<th class="label">' . ($$_{required} ? qq[<strong class="required">$$_{label}:</strong>] : "$$_{label}:") . '</th>'; 
     325                if ($$_{invalid}) { 
     326                    $OUT .= qq[<td>$$_{field} $$_{comment} Missing or invalid value.</td></tr>\n]; 
     327                } else { 
     328                    $OUT .= qq[<td>$$_{field} $$_{comment}</td></tr>\n]; 
     329                } 
     330            } elsif ($$line[0] eq 'group') { 
     331                my @field_names = map { $$_{name} } @{ $$line[1]{group} }; 
     332                my @group_fields = map { $field{$_} } @field_names; 
     333                $OUT .= (grep { $$_{invalid} } @group_fields) ? qq[  <tr class="invalid">\n] : qq[  <tr>\n]; 
     334                 
     335                $OUT .= '    <th class="label">'; 
     336                $OUT .= (grep { $$_{required} } @group_fields) ? qq[<strong class="required">$$line[1]{label}:</strong>] : "$$line[1]{label}:"; 
     337                $OUT .= qq[</th>\n]; 
     338                 
     339                $OUT .= qq[    <td>]; 
     340                $OUT .= join(' ', map { qq[<small class="sublabel">$$_{label}</small> $$_{field} $$_{comment}] } @group_fields); 
     341                $OUT .= qq[    </td>\n]; 
     342                $OUT .= qq[  </tr>\n]; 
     343            }    
    319344        } 
    320     } elsif ($$line[0] eq 'group') { 
    321         my @field_names = map { $$_{name} } @{ $$line[1]{group} }; 
    322         my @group_fields = map { $field{$_} } @field_names; 
    323         $OUT .= (grep { $$_{invalid} } @group_fields) ? qq[  <tr class="invalid">\n] : qq[  <tr>\n]; 
    324          
    325         $OUT .= '    <th class="label">'; 
    326         $OUT .= (grep { $$_{required} } @group_fields) ? qq[<strong class="required">$$line[1]{label}:</strong>] : "$$line[1]{label}:"; 
    327         $OUT .= qq[</th>\n]; 
    328          
    329         $OUT .= qq[    <td>]; 
    330         $OUT .= join(' ', map { qq[<small class="sublabel">$$_{label}</small> $$_{field} $$_{comment}] } @group_fields); 
    331         $OUT .= qq[    </td>\n]; 
    332         $OUT .= qq[  </tr>\n]; 
    333     }    
    334      
    335  
    336 } %> 
     345        # close the table if there are sections remaining 
     346        # but leave the last one open for the submit button 
     347        $OUT .= qq[</table>\n] if @sections; 
     348    } 
     349%> 
    337350  <tr><th></th><td style="padding-top: 1em;"><% $submit %></td></tr> 
    338351</table> 
     
    347360  <title><% $title %><% $author ? ' - ' . ucfirst $author : '' %></title> 
    348361  <style type="text/css"> 
     362    table { margin: .5em 1em; } 
    349363    #author, #footer { font-style: italic; } 
     364    caption h2 { padding: .125em .5em; background: #ddd; text-align: left; } 
    350365    th { text-align: left; } 
    351     th h2 { padding: .125em .5em; background: #eee; } 
     366    th h3 { padding: .125em .5em; background: #eee; } 
    352367    th.label { font-weight: normal; text-align: right; vertical-align: top; } 
    353368    td ul { list-style: none; padding-left: 0; margin-left: 0; } 
     
    475490    $parser->write; 
    476491 
    477 Calls C<render> on the FormBuilder form, and either writes the resulting HTML 
    478 to a file, or to STDOUT if no filename is given. 
     492Calls C<render> on the FormBuilder form, and either writes the resulting 
     493HTML to a file, or to STDOUT if no filename is given. 
     494 
     495CSS Hint: to get multiple sections to all line up their fields, set a 
     496standard width for th.label 
    479497 
    480498=head2 write_module 
     
    545563    !list name &{ CODE } 
    546564     
     565    !section id heading 
     566     
    547567    !head ... 
    548568 
     
    567587A brief description of the form. Suitable for special instructions on how to 
    568588fill out the form. 
     589 
     590=item C<!section> 
     591 
     592Starts a new section. Each section has its own heading and id, which are 
     593written by default into spearate tables. 
    569594 
    570595=item C<!head> 
     
    724749Use the custom message file format for messages in the built in template 
    725750 
    726 C<!section> directive to split up the table into multiple tables, each 
    727 with their own id and (optional) heading 
     751Custom CSS, both in addition to, and replacing the built in. 
    728752 
    729753Use HTML::Template instead of Text::Template for the built in template 
     
    751775Thanks to eszpee for pointing out some bugs in the default value parsing, 
    752776as well as some suggestions for i18n/l10n and splitting up long forms into 
    753 sections (that as of this release are still on the TODO list ;-). 
     777sections. 
    754778 
    755779=head1 AUTHOR 
  • trunk/lib/Text/FormBuilder/grammar

    r28 r29  
    22    my ( 
    33        $context,      # line or group 
    4         @lines,        # master data structure 
     4        @sections,     # master data structure 
     5        $section_head, 
     6        $section_id, 
     7        @lines,        # lines in each section 
    58        $title, 
    69        $author, 
     
    2326form_spec: (list_def | description_def | group_def | line)(s) 
    2427    { 
     28        # grab the last section, if there is any 
     29        if (@lines) { 
     30            push @sections, 
     31                { 
     32                    id   => $section_id, 
     33                    head => $section_head, 
     34                    lines => [ @lines ], 
     35                }; 
     36        } 
     37         
     38        $section_id = $item{identifier}; 
     39        $section_head = $item[3]; 
     40        @lines = (); 
    2541        $return = { 
    2642            title    => $title, 
     
    2945            lists    => \%lists, 
    3046            patterns => \%patterns, 
    31             lines    => \@lines, 
    3247            groups   => \%groups, 
     48            sections => \@sections, 
    3349        } 
    3450    } 
     
    6480 
    6581field_line: <skip:'[ \t]*'> ( field | comment | blank ) "\n" 
    66 line: <skip:'[ \t]*'> ( title | author | pattern_def | heading | group_field | unknown_directive | field | comment | blank ) "\n" 
     82line: <skip:'[ \t]*'> ( title | author | pattern_def | section_head | heading | group_field | unknown_directive | field | comment | blank ) "\n" 
    6783 
    6884title: '!title' /.*/ 
     
    8298 
    8399pattern: /.*/ 
     100 
     101section_head: '!section' identifier /.*/ 
     102    { 
     103        #warn "starting section $item{identifier}\n"; 
     104        #warn "  with heading $item[3]\n" if $item[3]; 
     105         
     106        if (@lines) { 
     107            push @sections, 
     108                { 
     109                    id   => $section_id, 
     110                    head => $section_head, 
     111                    lines => [ @lines ], 
     112                }; 
     113        } 
     114         
     115        $section_id = $item{identifier}; 
     116        $section_head = $item[3]; 
     117        @lines = (); 
     118    } 
    84119 
    85120heading: '!head' /.*/    { push @lines, [ 'head', $item[2] ] } 
Note: See TracChangeset for help on using the changeset viewer.