X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=lib%2FMaypole%2FModel%2FCDBI%2FAsForm.pm;h=66ccaf6d507a703f2e3f8e14e126bbbf096487ca;hb=02b642b7100a6e0a91e83aca3c4e63cd88786315;hp=ef67a06e14ef4c8fd6ec0c2957da8a1e17773876;hpb=446373ada20165687d0c3b03a2ee18c08831be02;p=maypole.git diff --git a/lib/Maypole/Model/CDBI/AsForm.pm b/lib/Maypole/Model/CDBI/AsForm.pm index ef67a06..66ccaf6 100644 --- a/lib/Maypole/Model/CDBI/AsForm.pm +++ b/lib/Maypole/Model/CDBI/AsForm.pm @@ -11,8 +11,6 @@ package Maypole::Model::CDBI::AsForm; # -- $class->to_field($has_many_col); # foreign inputs # $class->search_inputs; / -use 5.006; - use strict; use warnings; @@ -32,18 +30,10 @@ our @EXPORT = _to_foreign_inputs _to_enum_select _to_bool_select _to_hidden _to_link_hidden _rename_foreign_input _to_readonly _options_from_objects _options_from_arrays _options_from_hashes - _options_from_scalars _to_select_or_create + _options_from_array _options_from_hash _to_select_or_create ); - -our @EXPORTOK = - qw( - - - ); - - -our $VERSION = '.10'; +our $VERSION = '.10'; =head1 NAME @@ -117,13 +107,15 @@ example usages. $beer->to_field($col, $args); Not all _to_* methods pay attention to all arguments. For example, '_to_textfield' does not look in $args->{'items'} at all. - + +=over + =item name -- the name the element will have , this trumps the derived name. $beer->to_field('brewery', 'readonly', { name => 'brewery_id' }); - + =item value -- the initial value the element will have, trumps derived value $beer->to_field('brewery', 'textfield', { @@ -199,12 +191,13 @@ static values. You can also specify these in the relationship arguments. constraint => {location => 'London'}, 'join' => {'brewery_tablecolumn => 'beer_obj_column'}, ); - + =item no_hidden_constraints -- Tell AsForm not to make hidden inputs for relationship constraints. It does this sometimes when making foreign inputs . +=back =head2 to_cgi @@ -362,6 +355,11 @@ sub search_inputs { } +=head2 unselect_element + + unselect any selected elemets in a HTML::Element select list widget + +=cut # sub unselect_element { @@ -462,7 +460,8 @@ sub _field_from_relationship { } return; } - + + =head2 _field_from_column($field, $args) Returns an input based on the column's characteristics, namely type, or nothing. @@ -653,7 +652,7 @@ sub _to_select { my ($self, $col, $args) = @_; $args ||= {}; # Do we have items already ? Go no further. - if ($args->{items} and @{$args->{items}}) { + if ($args->{items} and ref $args->{items}) { my $a = $self->_select_guts($col, $args); $OLD_STYLE && return $a->as_HTML; if ($args->{multiple}) { $a->attr('multiple', 'multiple');} @@ -1083,9 +1082,12 @@ sub _hash_selected { Internal api method to make the actual select box form elements. 3 types of lists making for -- + Hash, Array, Array of CDBI objects. Array of scalars , - Array or Array refs with cols from class. + Array or Array refs with cols from class, + Array of hashes + =cut @@ -1106,37 +1108,39 @@ sub _select_guts { $a->push_content($null_element); } - my $items = $args->{items}; - my $proto = $items->[0]; - my $type = ref $proto || ''; - - # Objects - if (not $type) { - $a->push_content($self->_options_from_scalars($items, $args)); - } - elsif($type !~ /ARRAY|HASH/i) { - # make select of objects - $a->push_content($self->_options_from_objects($items, $args)); - } - elsif ($type =~ /ARRAY/i) { - $a->push_content($self->_options_from_arrays($items, $args)); + my $items = $args->{items}; + my $type = ref $items; + my $proto = eval { ref $items->[0]; } || ""; + warn "Type is $type, proto is $proto\n"; + # Single Hash + if ($type eq 'HASH') { + $a->push_content($self->_options_from_hash($items, $args)); + } + # Single Array + elsif ( $type eq 'ARRAY' and not ref $items->[0] ) { + $a->push_content($self->_options_from_array($items, $args)); + } + # Array of Objects + elsif( $type eq 'ARRAY' and $proto !~ /ARRAY|HASH/i ) { + # make select of objects + $a->push_content($self->_options_from_objects($items, $args)); } - elsif ($type =~ /HASH/i) { - $a->push_content($self->_options_from_hashes($items, $args)); + # Array of Arrays + elsif ( $type eq 'ARRAY' and $proto eq 'ARRAY' ) { + $a->push_content($self->_options_from_arrays($items, $args)); } - else { - die "You passed a weird type of data structure to me. Here it is: $type"; + # Array of Hashes + elsif ( $type eq 'ARRAY' and $proto eq 'HASH' ) { + $a->push_content($self->_options_from_hashes($items, $args)); + } + else { + die "You passed a weird type of data structure to me. Here it is: " . + Dumper($items ); } return $a; } - - - - - - =head2 _options_from_objects ( $objects, $args); Private method to makes a options out of objects. It attempts to call each @@ -1181,20 +1185,39 @@ sub _options_from_arrays { return @res; } -sub _options_from_scalars { + +sub _options_from_array { my ($self, $items, $args) = @_; - my $selected = $args->{selected} || {}; + my $selected = $args->{selected} || {}; my @res; - for (@$items) { - my $opt = HTML::Element->new("option", value => $_ ); - #$opt->attr(selected => "selected") if $selected =~/^$id$/; - $opt->attr(selected => "selected") if $selected->{$_}; - $opt->push_content( $_ ); - push @res, $opt; + for (@$items) { + my $opt = HTML::Element->new("option", value => $_ ); + #$opt->attr(selected => "selected") if $selected =~/^$id$/; + $opt->attr(selected => "selected") if $selected->{$_}; + $opt->push_content( $_ ); + push @res, $opt; + } + return @res; +} + +sub _options_from_hash { + my ($self, $items, $args) = @_; + my $selected = $args->{selected} || {}; + my @res; + + my @values = values %$items; + # hash Key is the option content and the hash value is option value + for (sort keys %$items) { + my $opt = HTML::Element->new("option", value => $items->{$_} ); + #$opt->attr(selected => "selected") if $selected =~/^$id$/; + $opt->attr(selected => "selected") if $selected->{$items->{$_}}; + $opt->push_content( $_ ); + push @res, $opt; } return @res; } + sub _options_from_hashes { my ($self, $items, $args) = @_; my $selected = $args->{selected} || {}; @@ -1206,7 +1229,7 @@ sub _options_from_hashes { my $val = $_->{$pk}; my $opt = HTML::Element->new("option", value => $val ); $opt->attr(selected => "selected") if $selected->{$val}; - my $content = $fclass and $stringify and $fclass->can($stringify) ? + my $content = ($fclass and $stringify and $fclass->can($stringify)) ? $fclass->$stringify($_) : join(' ', @$_); $opt->push_content( $content ); @@ -1223,12 +1246,9 @@ sub _to_select_or_create { my $create = $self->to_field($col, 'foreign_inputs', $args); $create->{'__select_or_create__'} = $self->to_field('__select_or_create__',{ name => '__select_or_create__' , value => 1 } ); - return ($select, $create); } - - - + # # checkboxes: if no data in hand (ie called as class method), replace # with a radio button, in order to allow this field to be left @@ -1241,7 +1261,6 @@ sub _to_select_or_create { sub _to_checkbox { my ($self, $col, $args) = @_; my $nullable = eval {self->column_nullable($col)} || 0; - return $self->_to_radio($col) if !ref($self) || $nullable; my $value = $self->$col; my $a = HTML::Element->new("input", type=> "checkbox", name => $col); @@ -1326,7 +1345,8 @@ sub _rename_foreign_input { foreach (keys %$element); } } -=head2 _box($value) + +=head2 _box($value) This functions computes the dimensions of a textarea based on the value or the defaults. @@ -1334,6 +1354,7 @@ or the defaults. =cut our ($min_rows, $max_rows, $min_cols, $max_cols) = (2 => 50, 20 => 100); + sub _box { my $text = shift;