From 04a420e0bd0eb3bd92c848b838c102f5bb01677a Mon Sep 17 00:00:00 2001 From: Doug Bell Date: Tue, 12 Apr 2011 21:26:20 -0500 Subject: [PATCH] formbuilder toTemplateVars is now complete and tested --- lib/WebGUI/FormBuilder.pm | 113 +++++-------------- lib/WebGUI/FormBuilder/Fieldset.pm | 11 +- lib/WebGUI/FormBuilder/Role/HasFields.pm | 7 +- lib/WebGUI/FormBuilder/Role/HasObjects.pm | 66 ++++++++++- lib/WebGUI/FormBuilder/Tab.pm | 16 +++ lib/WebGUI/FormBuilder/Tabset.pm | 16 ++- t/FormBuilder.t | 130 ++++++++++++++++++++-- 7 files changed, 254 insertions(+), 105 deletions(-) diff --git a/lib/WebGUI/FormBuilder.pm b/lib/WebGUI/FormBuilder.pm index e59017603..dae2f414b 100644 --- a/lib/WebGUI/FormBuilder.pm +++ b/lib/WebGUI/FormBuilder.pm @@ -1,6 +1,7 @@ package WebGUI::FormBuilder; use strict; +use WebGUI::BestPractices; use Moose; use MooseX::Storage; @@ -70,6 +71,19 @@ The name of the form. Not required, but recommended. has 'name' => ( is => 'rw' ); +=head2 class + +The class name for the element. Defaults to "wg-formbuilder" and pulls in the +style rules from extras/css/wg-formbuilder.css. Multiple class names may be +seperated by a space. + +You should probably keep the default class and either add additional classes +or override .wg-formbuilder in your custom CSS files. + +=cut + +has class => ( is => 'rw', default => 'wg-formbuilder' ); + =head2 extras Any extra things to add to the
tag. Optional. @@ -157,7 +171,7 @@ Get the header for this form. sub getHeader { my ( $self ) = @_; - my @attrs = qw{ action method name enctype }; + my @attrs = qw{ action method name enctype class }; my $attrs = join " ", map { qq{$_="} . $self->$_ . qq{"} } grep { $self->$_ } @attrs; my $html = sprintf '', $attrs, $self->extras; @@ -177,10 +191,11 @@ sub toHtml { my ( $self ) = @_; my ( $style, $url ) = $self->session->quick(qw{ style url }); - $style->setCss( $url->extras('hoverhelp.css')); + $style->setCss( $url->extras('css/wg-formbuilder.css') ); $style->setScript( $url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js') ); $style->setScript( $url->extras('yui/build/container/container-min.js') ); $style->setScript( $url->extras('hoverhelp.js') ); + $style->setCss( $url->extras('hoverhelp.css')); my $html = $self->getHeader; # Add individual objects @@ -199,97 +214,23 @@ sub toHtml { #---------------------------------------------------------------------------- -=head2 toTemplateVars ( prefix, [var] ) +=head2 toTemplateVars ( prefix, var ) -Get the template variables for the form's controls with the given prefix. -C is an optional hashref to add the variables to. +Get the template variables for the form's controls with the given prefix. C +defaults to "form_". C is an optional hashref to add the variables to. =cut -sub toTemplateVars { - my ( $self, $prefix, $var ) = @_; - $prefix ||= "form"; - $var ||= {}; +around toTemplateVars => sub { + my ( $orig, $self, $prefix, $var ) = @_; + $prefix ||= "form_"; + $var = $self->$orig($prefix, $var); - # $prefix_header - $var->{ "${prefix}_header" } = $self->getHeader; - # $prefix_footer - $var->{ "${prefix}_footer" } = $self->getFooter; - # $prefix_fieldloop - # name -- for comparisons - # field - # label -- includes hoverhelp - # label_nohover - # pretext - # subtext - # hoverhelp -- The text. For use with label_nohover - # $prefix_field_$fieldName - if ( @{$self->fields} ) { - my $fieldLoop = []; - $var->{ "${prefix}_fieldloop" } = $fieldLoop; - for my $field ( @{$self->fields} ) { - my $name = $field->get('name'); - my $props = $field->toTemplateVars; - # Add the whole field to the vars - $props->{ field } = $field->toHtml; - $var->{ "${prefix}_field_${name}" } = $props->{ field }; - push @{$fieldLoop}, $props; - # Individual accessor - for my $key ( keys %{$props} ) { - $var->{ "${prefix}_field_${name}_${key}" } = $props->{$key}; - } - # Loop accessor - push @{$var->{ "${prefix}_field_${name}_loop" }}, $props; - } - } - # $prefix_fieldsetloop - # name - # legend - # label -- same as legend - # fieldloop - # ... - # fieldsetloop - # ... - # tabloop - # ... - # $prefix_fieldset_$fieldsetName - if ( @{$self->fieldsets} ) { - my $fieldsetLoop = []; - $var->{ "${prefix}_fieldsetloop" } = $fieldsetLoop; - for my $fieldset ( @{$self->fieldsets} ) { - my $name = $fieldset->name; - my $props = $fieldset->toTemplateVars; - for my $key ( keys %{$props} ) { - $var->{ "${prefix}_fieldset_${name}_${key}" } = $props->{key}; - } - push @{$fieldsetLoop}, $props; - } - } - # $prefix_tabsetloop - # name - # tabloop - # fieldloop - # ... - # fieldsetloop - # ... - # tabsetloop - # ... - # $prefix_tabset_$tabsetName - if ( @{$self->tabsets} ) { - my $tabsetLoop = []; - $var->{ "${prefix}_tabsetloop" } = $tabsetLoop; - for my $tabset ( @{$self->tabsets} ) { - my $name = $tabset->name; - my $props = $tabset->toTemplateVars; - for my $key ( keys %{$props} ) { - $var->{ "${prefix}_tabset_${name}_${key}" } = $props->{key}; - } - push @{$tabsetLoop}, $props; - } - } + $var->{ "${prefix}header" } = $self->getHeader; + $var->{ "${prefix}footer" } = $self->getFooter; return $var; -} +}; =head1 TEMPLATES diff --git a/lib/WebGUI/FormBuilder/Fieldset.pm b/lib/WebGUI/FormBuilder/Fieldset.pm index 1208d61ab..dd646feb8 100644 --- a/lib/WebGUI/FormBuilder/Fieldset.pm +++ b/lib/WebGUI/FormBuilder/Fieldset.pm @@ -144,8 +144,13 @@ sub toHtml { =cut -sub toTemplateVars { - -} +around toTemplateVars => sub { + my ( $orig, $self ) = @_; + my $var = $self->$orig(); + $var->{ name } = $self->name; + $var->{ label } = $self->label; + $var->{ legend } = $self->label; + return $var; +}; 1; diff --git a/lib/WebGUI/FormBuilder/Role/HasFields.pm b/lib/WebGUI/FormBuilder/Role/HasFields.pm index e9200f561..2295e60aa 100644 --- a/lib/WebGUI/FormBuilder/Role/HasFields.pm +++ b/lib/WebGUI/FormBuilder/Role/HasFields.pm @@ -91,9 +91,10 @@ sub addFieldAt { for my $obj ( @{$self->objects} ) { next unless blessed $obj; # A field isn't allowed to have child objects - if ( !$obj->can('does') || !$obj->does('WebGUI::FormBuilder::Role::HasObjects') ) { - push @{$self->fields}, $obj; - } + next if ( $obj->can('does') && $obj->does('WebGUI::FormBuilder::Role::HasObjects') ); + next if $obj->isa('WebGUI::FormBuilder::Tabset'); + + push @{$self->fields}, $obj; } return $field; } diff --git a/lib/WebGUI/FormBuilder/Role/HasObjects.pm b/lib/WebGUI/FormBuilder/Role/HasObjects.pm index f3641cd04..234507aa1 100644 --- a/lib/WebGUI/FormBuilder/Role/HasObjects.pm +++ b/lib/WebGUI/FormBuilder/Role/HasObjects.pm @@ -14,7 +14,7 @@ package WebGUI::FormBuilder::Role::HasObjects; =cut - +use WebGUI::BestPractices; use Moose::Role; has 'objects' => ( @@ -80,5 +80,69 @@ sub addObjectAt { return $object; } +=head2 toTemplateVars ( prefix, var ) + +Get all the objects as a set of template vars with the given prefix. $var is +an optional hashref to add the variables to. + +=cut + +sub toTemplateVars { + my ( $self, $prefix, $var ) = @_; + $prefix ||= ""; + $var ||= {}; + + # Loop over all objects, adding to appropriate template loops + for my $obj ( @{ $self->objects } ) { + # Prepare our object's variables and add to object type loop + my $props = {}; + + given ( blessed $obj ) { + when ( undef ) { + # Treat as raw template properties + $props = $obj; + } + when ( $_->isa( 'WebGUI::FormBuilder::Tabset' ) ) { + my $name = $obj->name; + $props = $obj->toTemplateVars; + for my $key ( keys %{$props} ) { + $var->{ "${prefix}tabset_${name}_${key}" } = $props->{$key}; + } + push @{$var->{ "${prefix}tabsetloop" }}, $props; + } + when ( $_->isa( 'WebGUI::FormBuilder::Fieldset' ) ) { + my $name = $obj->name; + $props = $obj->toTemplateVars; + for my $key ( keys %{$props} ) { + $var->{ "${prefix}fieldset_${name}_${key}" } = $props->{$key}; + } + push @{$var->{ "${prefix}fieldsetloop" }}, $props; + } + # Form field objects + when ( $_->isa( 'WebGUI::Form::Control' ) ) { + my $name = $obj->get('name'); + $props = $obj->toTemplateVars; + # Add the whole field to the vars + $props->{ field } = $obj->toHtmlWithWrapper; + $props->{ field_input } = $obj->toHtml; + $var->{ "${prefix}field_${name}" } = $props->{ field }; + # Add to fieldloop + push @{$var->{"${prefix}fieldloop"}}, $props; + # Individual accessors + for my $key ( keys %{$props} ) { + $var->{ "${prefix}field_${name}_${key}" } = $props->{$key}; + } + # Loop accessor + push @{$var->{ "${prefix}field_${name}_loop" }}, $props; + } + } + + # Add to the global object loop + push @{ $var->{ "${prefix}objects" } }, $props; + } + + return $var; +} + 1; diff --git a/lib/WebGUI/FormBuilder/Tab.pm b/lib/WebGUI/FormBuilder/Tab.pm index 2d216d8d3..88a0dddbd 100644 --- a/lib/WebGUI/FormBuilder/Tab.pm +++ b/lib/WebGUI/FormBuilder/Tab.pm @@ -105,4 +105,20 @@ sub toHtml { return $html; } +#---------------------------------------------------------------------------- + +=head2 toTemplateVars ( ) + +Get the template vars for this tab + +=cut + +around toTemplateVars => sub { + my ( $orig, $self ) = @_; + my $var = $self->$orig(); + $var->{ name } = $self->name; + $var->{ label } = $self->label; + return $var; +}; + 1; diff --git a/lib/WebGUI/FormBuilder/Tabset.pm b/lib/WebGUI/FormBuilder/Tabset.pm index e5e966ab7..109b19a6e 100644 --- a/lib/WebGUI/FormBuilder/Tabset.pm +++ b/lib/WebGUI/FormBuilder/Tabset.pm @@ -71,7 +71,6 @@ has 'session' => ( ); with Storage( format => 'JSON' ); -with 'WebGUI::FormBuilder::Role::HasObjects'; #---------------------------------------------------------------------------- @@ -90,9 +89,15 @@ sub BUILDARGS { #---------------------------------------------------------------------------- sub addTab { - my ( $self, $tab ) = @_; + my $self = shift; + my $tab; + if ( scalar @_ == 1 ) { + $tab = $_[0]; + } + else { + $tab = WebGUI::FormBuilder::Tab->new( $self->session, @_ ); + } push @{$self->tabs}, $tab; - $self->addObject( $tab ); return $tab; } @@ -151,13 +156,14 @@ sub toTemplateVars { my ( $self ) = @_; my $var = {}; + $var->{ name } = $self->name; $var->{ tabs } = []; - for my $tab ( $self->tabs ) { + for my $tab ( @{ $self->tabs } ) { my $name = $tab->name; my $props = $tab->toTemplateVars; $var->{ "tabs_${name}" } = $tab->toHtml; push @{$var->{tabs}}, $props; - for my $key ( %$props ) { + for my $key ( keys %{$props} ) { $var->{ "tabs_${name}_${key}" } = $props->{$key}; } } diff --git a/t/FormBuilder.t b/t/FormBuilder.t index 1cbfa3616..8c84b375f 100644 --- a/t/FormBuilder.t +++ b/t/FormBuilder.t @@ -13,11 +13,16 @@ # # +use warnings; use strict; use Test::More; use Test::Deep; use WebGUI::Test; # Must use this before any other WebGUI modules use WebGUI::Session; +use WebGUI::BestPractices; + +use Carp; +$SIG{ __DIE__ } = sub { Carp::confess( @_ ) }; #---------------------------------------------------------------------------- # Init @@ -155,7 +160,7 @@ cmp_deeply( ); # addFieldset with objects -my $field = $fset->addField( +$field = $fset->addField( 'WebGUI::Form::Text' => ( name => 'search', value => "Search Now", @@ -165,7 +170,7 @@ my $subfset = $fset->addFieldset( name => 'advanced', label => 'Advanced Search', ); -my $tab = $fset->addTab( +$tab = $fset->addTab( name => 'more', label => 'More', ); @@ -200,7 +205,7 @@ ok( !$fb->getFieldset('newname'), 'deleted fieldset cannot be gotten' ); # addField with properties $fb = WebGUI::FormBuilder->new( $session ); -my $field = $fb->addField( +$field = $fb->addField( 'Text' => ( name => 'search', value => 'Search Now', @@ -263,17 +268,128 @@ cmp_deeply( #---------------------------------------------------------------------------- # Serialize and deserialize -my $fb = WebGUI::FormBuilder->new( $session ); -my $fset = $fb->addFieldset( name => 'search', label => 'Search' ); +$fb = WebGUI::FormBuilder->new( $session ); +$fset = $fb->addFieldset( name => 'search', label => 'Search' ); $fset->addField( 'text', name => 'keywords', label => 'Keywords' ); -my $tab = $fb->addTab( name => 'advanced', label => 'Advanced Search' ); +$tab = $fb->addTab( name => 'advanced', label => 'Advanced Search' ); $tab->addField( 'text', name => 'type', label => 'Type' ); $fb->addField( 'submit', name => 'submit', label => 'Submit' ); #---------------------------------------------------------------------------- -# toHtml +# toTemplateVars +$fb = WebGUI::FormBuilder->new( $session ); +$field = $fb->addField( 'Text', name => 'field1' ); +my $fieldset = $fb->addFieldset( name => 'two', label => 'Two' ); +my $fieldsetField = $fieldset->addField( 'Text', name => 'two one' ); +$tab = $fb->addTab( name => 'three 1', label => 'Three 1' ); +$tab->addField( 'Text', name => 'three 1 1' ); +my $tab2 = $fb->addTab( name => 'three 2', label => 'Three 2' ); +$tab2->addField( 'Checkbox', name => 'three 2 1' ); +$tab2->addField( 'Checkbox', name => 'three 2 1' ); +$field2 = $fb->addField( 'Submit', name => 'submit' ); +$field3 = $fb->addField( 'Button', name => 'cancel' ); + +my $expected_var = { + header => $fb->getHeader, + footer => $fb->getFooter, + %{ object_vars( $fb ) }, +}; + +# Add the prefix +$expected_var = { map { ("fb_$_" => delete $expected_var->{$_}) } keys %$expected_var }; + +cmp_deeply( + $fb->toTemplateVars('fb_'), + $expected_var, + 'toTemplateVars complete and correct' +); done_testing; + +sub field_vars { + my $field = shift; + my $var = { + field => $field->toHtmlWithWrapper, + field_input => $field->toHtml, + %{$field->toTemplateVars}, # not testing field's toTemplateVars method + }; + return $var; +} + +sub fieldset_vars { + my $fieldset = shift; + return { + name => $fieldset->name, + label => $fieldset->label, + legend => $fieldset->legend, + %{object_vars( $fieldset )}, + }; +} + +sub tabset_vars { + my $tabset = shift; + my $var = { + name => $tabset->name, + tabs => [ map { { %{object_vars( $_ )}, name => $_->name, label => $_->label } } @{$tabset->tabs} ], + }; + for my $tab ( @{ $var->{tabs} } ) { + my $name = $tab->{name}; + $var->{ "tabs_${name}" } = ignore(); # Ignore html for tabs, just as long as it's there + for my $key ( keys %$tab ) { + $var->{ "tabs_${name}_${key}" } = $tab->{ $key }; + } + } + return $var; +} + +sub object_vars { + my $f = shift; + my $var = {}; + + # Stream of objects + for my $obj ( @{$f->objects} ) { + use Scalar::Util qw(blessed); + given ( blessed $obj ) { + when ( undef ) { + push @{$var->{objects}}, $obj; + } + when ( $_->isa( 'WebGUI::FormBuilder::Tabset' ) ) { + my $props = tabset_vars( $obj ); + my $name = $props->{name}; + for my $key ( keys %$props ) { + $var->{ "tabset_${name}_${key}" } = $props->{$key}; + } + push @{ $var->{tabsetloop} }, $props; + push @{$var->{objects}}, $props; + } + when ( $_->isa( 'WebGUI::FormBuilder::Fieldset' ) ) { + my $props = fieldset_vars( $obj ); + my $name = $props->{name}; + for my $key ( keys %$props ) { + $var->{ "fieldset_${name}_${key}" } = $props->{$key}; + } + push @{ $var->{fieldsetloop} }, $props; + push @{$var->{objects}}, $props; + } + when ( $_->isa( 'WebGUI::Form::Control' ) ) { + my $props = field_vars( $obj ); + my $name = $props->{name}; + for my $key ( keys %$props ) { + $var->{ "field_${name}_${key}" } = $props->{$key}; + } + push @{$var->{ "field_${name}_loop" }}, $props; + push @{ $var->{fieldloop} }, $props; + $var->{ "field_${name}" } = $props->{field}; + push @{$var->{objects}}, $props; + } + } + } + + return $var; +} + #vim:ft=perl + +