Changeset 29 in text-formbuilder
- Timestamp:
- 11/17/04 10:03:41 (20 years ago)
- Location:
- trunk/lib/Text
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/lib/Text/FormBuilder.pm
r28 r29 87 87 # expand groups 88 88 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 } ]; 98 103 } 99 $_ = [ 'group', { label => $$_[1]{label} || ucfirst(join(' ',split('_',$$_[1]{name}))), group => \@fields } ];100 104 } 101 105 } 102 106 103 107 $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 } 109 117 } 110 118 } 111 112 119 113 120 # substitute in list names … … 149 156 $$_{required} or delete $$_{required} foreach @{ $self->{form_spec}{fields} }; 150 157 151 158 # need to explicity set the fields so that simple text fields get picked up 152 159 $self->{form} = CGI::FormBuilder->new( 153 160 %DEFAULT_OPTIONS, 161 fields => [ map { $$_{name} } @{ $self->{form_spec}{fields} } ], 154 162 required => [ map { $$_{name} } grep { $$_{required} } @{ $self->{form_spec}{fields} } ], 155 163 title => $self->{form_spec}{title}, … … 163 171 }, 164 172 data => { 165 lines => $self->{form_spec}{lines},173 sections => $self->{form_spec}{sections}, 166 174 author => $self->{form_spec}{author}, 167 175 description => $self->{form_spec}{description}, … … 214 222 title => $self->{form_spec}{title}, 215 223 text => $self->{form_spec}{description}, 224 fields => [ map { $$_{name} } @{ $self->{form_spec}{fields} } ], 216 225 required => [ map { $$_{name} } grep { $$_{required} } @{ $self->{form_spec}{fields} } ], 217 226 template => { … … 223 232 }, 224 233 data => { 225 lines => $self->{form_spec}{lines},234 sections => $self->{form_spec}{sections}, 226 235 author => $self->{form_spec}{author}, 227 236 description => $self->{form_spec}{description}, … … 299 308 %> 300 309 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 } 319 344 } 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 %> 337 350 <tr><th></th><td style="padding-top: 1em;"><% $submit %></td></tr> 338 351 </table> … … 347 360 <title><% $title %><% $author ? ' - ' . ucfirst $author : '' %></title> 348 361 <style type="text/css"> 362 table { margin: .5em 1em; } 349 363 #author, #footer { font-style: italic; } 364 caption h2 { padding: .125em .5em; background: #ddd; text-align: left; } 350 365 th { text-align: left; } 351 th h 2{ padding: .125em .5em; background: #eee; }366 th h3 { padding: .125em .5em; background: #eee; } 352 367 th.label { font-weight: normal; text-align: right; vertical-align: top; } 353 368 td ul { list-style: none; padding-left: 0; margin-left: 0; } … … 475 490 $parser->write; 476 491 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. 492 Calls C<render> on the FormBuilder form, and either writes the resulting 493 HTML to a file, or to STDOUT if no filename is given. 494 495 CSS Hint: to get multiple sections to all line up their fields, set a 496 standard width for th.label 479 497 480 498 =head2 write_module … … 545 563 !list name &{ CODE } 546 564 565 !section id heading 566 547 567 !head ... 548 568 … … 567 587 A brief description of the form. Suitable for special instructions on how to 568 588 fill out the form. 589 590 =item C<!section> 591 592 Starts a new section. Each section has its own heading and id, which are 593 written by default into spearate tables. 569 594 570 595 =item C<!head> … … 724 749 Use the custom message file format for messages in the built in template 725 750 726 C<!section> directive to split up the table into multiple tables, each 727 with their own id and (optional) heading 751 Custom CSS, both in addition to, and replacing the built in. 728 752 729 753 Use HTML::Template instead of Text::Template for the built in template … … 751 775 Thanks to eszpee for pointing out some bugs in the default value parsing, 752 776 as 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 ;-).777 sections. 754 778 755 779 =head1 AUTHOR -
trunk/lib/Text/FormBuilder/grammar
r28 r29 2 2 my ( 3 3 $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 5 8 $title, 6 9 $author, … … 23 26 form_spec: (list_def | description_def | group_def | line)(s) 24 27 { 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 = (); 25 41 $return = { 26 42 title => $title, … … 29 45 lists => \%lists, 30 46 patterns => \%patterns, 31 lines => \@lines,32 47 groups => \%groups, 48 sections => \@sections, 33 49 } 34 50 } … … 64 80 65 81 field_line: <skip:'[ \t]*'> ( field | comment | blank ) "\n" 66 line: <skip:'[ \t]*'> ( title | author | pattern_def | heading | group_field | unknown_directive | field | comment | blank ) "\n"82 line: <skip:'[ \t]*'> ( title | author | pattern_def | section_head | heading | group_field | unknown_directive | field | comment | blank ) "\n" 67 83 68 84 title: '!title' /.*/ … … 82 98 83 99 pattern: /.*/ 100 101 section_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 } 84 119 85 120 heading: '!head' /.*/ { push @lines, [ 'head', $item[2] ] }
Note: See TracChangeset
for help on using the changeset viewer.