package CGI::Test::Form::Group; use strict; use warnings; ################################################################ # $Id: Group.pm 411 2011-09-26 11:19:30Z nohuhu@nohuhu.org $ # $Name: cgi-test_0-104_t1 $ ################################################################ # 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. # # This class records names of grouped objects (radio buttons, checkboxes), # and which buttons belong to some named group. # # # ->new # # 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 new { my $this = bless {}, shift; # The object is the hash table we use my ($rlist) = @_; # # Create map: "group name" => [list of buttons in group] # foreach my $b (@$rlist) { my $gname = $b->name; $this->{$gname} = [] unless exists $this->{$gname}; push @{$this->{$gname}}, $b; $b->set_group($this); } $this->_validate_radios() if $rlist->[ 0 ]->is_radio(); return $this; } # # Attribute access # sub names { my $this = shift; return keys %{$this}; } # # ->widgets_in # # Returns list of widgets held within named group, empty if none. # sub widgets_in { my $this = shift; my ($gname) = @_; my $list = $this->{$gname} || []; return @$list; } # # ->widget_count # # Returns amount of widgets held within named group, 0 if none. # sub widget_count { my $this = shift; my ($gname) = @_; my $list = $this->{$gname}; return ref $list ? scalar(@$list) : 0; } # # ->is_groupname # # Check whether name is that of a known widget group. # sub is_groupname { my $this = shift; my ($gname) = @_; return exists $this->{$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 { my $this = shift; foreach my $gname ($this->names) { my @checked = grep {$_->is_checked} $this->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. # warn "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 = $this->{$gname}->[ 0 ]; warn "no checked %ss for '%s', checking first (tag \"%s\")", $first->gui_type, $gname, ($first->value || ""); $first->{is_checked} = 1; # Direct access } } return; } 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 AUTHORS The original author is Raphael Manfredi. Steven Hilton was long time maintainer of this module. Current maintainer is Alexander Tokarev Ftokarev@cpan.orgE>. =head1 SEE ALSO CGI::Test::Form(3), CGI::Test::Form::Widget::Box(3). =cut