# # $Id: Group.pm,v 0.1 2001/03/31 10:54:01 ram Exp $ # # Copyright (c) 2001, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # # HISTORY # $Log: Group.pm,v $ # Revision 0.1 2001/03/31 10:54:01 ram # Baseline for first Alpha release. # # $EndLog$ # use strict; package CGI::Test::Form::Group; # # This class records names of grouped objects (radio buttons, checkboxes), # and which buttons belong to some named group. # use Carp::Datum; use Log::Agent; # # ->make # # Creation routine # # From a listref of box widgets, build a hash table indexed by group name # and listing all the buttons belonging to the named group. Each box is # also made aware of this object. # sub make { DFEATURE my $f_; my $self = bless {}, shift; # The object is the hash table we use my ($rlist) = @_; DREQUIRE ref $rlist eq 'ARRAY'; DREQUIRE @$rlist > 0; # # Create map: "group name" => [list of buttons in group] # foreach my $b (@$rlist) { DASSERT ref $b && $b->isa("CGI::Test::Form::Widget::Box"); my $gname = $b->name; $self->{$gname} = [] unless exists $self->{$gname}; push @{$self->{$gname}}, $b; $b->set_group($self); } $self->_validate_radios if $rlist->[0]->is_radio; return DVAL $self; } # # Attribute access # sub names { keys %{$_[0]} } # # ->widgets_in # # Returns list of widgets held within named group, empty if none. # sub widgets_in { DFEATURE my $f_; my $self = shift; my ($gname) = @_; my $list = $self->{$gname} || []; return DARY @$list; } # # ->widget_count # # Returns amount of widgets held within named group, 0 if none. # sub widget_count { DFEATURE my $f_; my $self = shift; my ($gname) = @_; my $list = $self->{$gname}; return DVAL ref $list ? scalar(@$list) : 0; } # # ->is_groupname # # Check whether name is that of a known widget group. # sub is_groupname { DFEATURE my $f_; my $self = shift; my ($gname) = @_; return DVAL exists $self->{$gname}; } # # ->_validate_radios # # When groupping radio buttons, make sure there is at least one such # button selected, otherwise mark the first as selected. Also ensure # exactly one radio is selected, or unselect all extra. # sub _validate_radios { DFEATURE my $f_; my $self = shift; foreach my $gname ($self->names) { my @checked = grep { $_->is_checked } $self->widgets_in($gname); my $checked = @checked; if ($checked > 1) { my $first = shift @checked; # # NB: we're not calling uncheck() nor set_is_checked() to fix # incorrectly configured radio buttons, since it is normally an # invalid operation. We're resettting the attribute directly. # logwarn "found %d checked %ss for '%s', keeping first (tag \"%s\")", $checked, $first->gui_type, $gname, ($first->value || ""); foreach my $b (@checked) { $b->{is_checked} = 0; # Direct access } } elsif ($checked == 0) { my $first = $self->{$gname}->[0]; logwarn "no checked %ss for '%s', checking first (tag \"%s\")", $first->gui_type, $gname, ($first->value || ""); $first->{is_checked} = 1; # Direct access } DASSERT 1 == grep($_->is_checked, $self->widgets_in($gname)), "exactly one radio button checked for group '$gname'"; } return DVOID; } 1; =head1 NAME CGI::Test::Form::Group - Records groups of box-type widgets =head1 SYNOPSIS # $form is a CGI::Test::Form object use CGI::Test; my $rgroup = $form->radio_groups; ok 1, defined $rgroup; my @title = $rgroup->widgets_in("title"); my ($mister) = grep { $_->value eq "Mr" } @title; ok 2, $mister->is_checked; =head1 DESCRIPTION This class is a container for box-type widgets, i.e. radio buttons and checkboxes, which may be groupped by name. It can be queried to easily retrieve widgets belonging to a group, or to get all the group names. It is also used internally by C to keep track of associated radio buttons, so that checking one automatically unchecks the others in the same group. =head1 INTERFACE The following features are available: =over 4 =item C I Checks whether I is the name of a group. =item C Returns a list of group names, in random order. =item C I Returns amount of widgets held in I, 0 if none. =item C I Returns a list of all the widgets in the given I. If the name is not a valid group name, the list will be empty. =back =head1 AUTHOR Raphael Manfredi FRaphael_Manfredi@pobox.comE> =head1 SEE ALSO CGI::Test::Form(3), CGI::Test::Form::Widget::Box(3). =cut