File Coverage

blib/lib/CGI/Test/Form/Widget/Box.pm
Criterion Covered Total %
statement 52 70 74.2
branch 4 10 40.0
condition n/a
subroutine 16 24 66.6
pod 14 16 87.5
total 86 120 71.6


line stmt bran cond sub pod time code
1             package CGI::Test::Form::Widget::Box;
2 14     14   64 use strict;
  14         18  
  14         346  
3 14     14   53 use warnings;
  14         8  
  14         275  
4             ##################################################################
5             # $Id: Box.pm 411 2011-09-26 11:19:30Z nohuhu@nohuhu.org $
6             # $Name: cgi-test_0-104_t1 $
7             ##################################################################
8             # Copyright (c) 2001, Raphael Manfredi
9             #
10             # You may redistribute only under the terms of the Artistic License,
11             # as specified in the README file that comes with the distribution.
12             #
13              
14 14     14   40 use Carp;
  14         20  
  14         581  
15              
16             #
17             # This class models a FORM box, either a radio button or a checkbox.
18             #
19              
20 14     14   46 use base qw(CGI::Test::Form::Widget);
  14         14  
  14         7640  
21              
22             ############################################################
23             #
24             # %attr
25             #
26             # Defines which HTML attributes we should look at within the node, and how
27             # to translate that into class attributes.
28             #
29             ############################################################
30              
31             my %attr = ('name' => 'name',
32             'value' => 'value',
33             'checked' => 'is_checked',
34             'disabled' => 'is_disabled',
35             );
36              
37             ############################################################
38             #
39             # ->_init
40             #
41             # Per-widget initialization routine.
42             # Parse HTML node to determine our specific parameters.
43             #
44             ############################################################
45             sub _init
46             {
47 128     128   100 my $this = shift;
48 128         110 my ($node) = shift;
49 128         266 $this->_parse_attr($node, \%attr);
50 128         137 return;
51             }
52              
53             ############################################################
54             #
55             # ->_is_successful -- defined
56             #
57             # Is the enabled widget "successful", according to W3C's specs?
58             # Any ticked checkbox and radio button is.
59             #
60             ############################################################
61             sub _is_successful
62             {
63 152     152   117 my $this = shift;
64 152         185 return $this->is_checked();
65             }
66              
67             ############################################################
68             #
69             # ->group_list
70             #
71             # Returns list of widgets belonging to the same group as we do.
72             #
73             ############################################################
74             sub group_list
75             {
76 12     12 1 14 my $this = shift;
77              
78 12         42 return $this->group->widgets_in($this->name);
79             }
80              
81             #
82             # Local attribute access
83             #
84              
85             ############################################################
86             sub group
87             {
88 13     13 1 13 my $this = shift;
89 13         48 return $this->{group};
90             }
91             ############################################################
92             sub is_checked
93             {
94 213     213 1 323 my $this = shift;
95 213         393 return $this->{is_checked};
96             }
97             ############################################################
98             sub old_is_checked
99             {
100 0     0 0 0 my $this = shift;
101 0         0 $this->{old_is_checked};
102             }
103              
104             #
105             # Checking shortcuts
106             #
107              
108             ############################################################
109             sub check
110             {
111 0     0 1 0 my $this = shift;
112 0         0 $this->set_is_checked(1);
113             }
114             ############################################################
115             sub uncheck
116             {
117 6     6 1 48 my $this = shift;
118 6         40 $this->set_is_checked(0);
119             }
120             ############################################################
121             sub check_tagged
122             {
123 6     6 1 110 my $this = shift;
124 6         10 my $tag = shift;
125 6         60 $this->_mark_by_tag($tag, 1);
126             }
127             ############################################################
128             sub uncheck_tagged
129             {
130 0     0 1 0 my $this = shift;
131 0         0 my $tag = shift;
132 0         0 $this->_mark_by_tag($tag, 0);
133             }
134              
135             #
136             # Attribute setting
137             #
138              
139             ############################################################
140             sub set_group
141             {
142 128     128 0 88 my $this = shift;
143 128         87 my $group = shift;
144 128         221 $this->{group} = $group;
145             }
146              
147             ############################################################
148             #
149             # ->set_is_checked
150             #
151             # Select or unselect box.
152             #
153             ############################################################
154             sub set_is_checked
155             {
156 6     6 1 10 my $this = shift;
157 6         8 my ($checked) = @_;
158              
159 6 50       18 return if !$checked == !$this->is_checked(); # No change
160              
161             #
162             # To ease redefinition, let this call _frozen_set_is_checked, which is
163             # not redefinable and performs the common operation.
164             #
165              
166 6         26 $this->_frozen_set_is_checked($checked);
167 6         10 return;
168             }
169              
170             ############################################################
171             #
172             # ->reset_state -- redefined
173             #
174             # Called when a "Reset" button is pressed to restore the value the widget
175             # had upon form entry.
176             #
177             ############################################################
178             sub reset_state
179             {
180 0     0 1 0 my $this = shift;
181              
182 0 0       0 $this->{is_checked} = delete $this->{old_is_checked}
183             if exists $this->{old_is_checked};
184              
185 0         0 return;
186             }
187              
188             #
189             # Global widget predicates
190             #
191              
192             ############################################################
193             sub is_read_only
194             {
195 0     0 1 0 return 1;
196             }
197              
198             #
199             # High-level classification predicates
200             #
201              
202             ############################################################
203             sub is_box
204             {
205 0     0 1 0 return 1;
206             }
207              
208             #
209             # Predicates for the Box hierarchy
210             #
211              
212             ############################################################
213             sub is_radio
214             {
215 0     0 1 0 confess "deferred";
216             }
217             ############################################################
218             sub is_standalone
219             {
220 1     1 1 2 my $this = shift;
221 1         6 1 == $this->group->widget_count($this->name());
222             }
223              
224             #
225             # ->delete
226             #
227             # Break circular refs.
228             #
229             sub delete
230             {
231 0     0 1 0 my $this = shift;
232              
233 0         0 delete $this->{group};
234 0         0 $this->SUPER::delete;
235              
236 0         0 return;
237             }
238              
239             #
240             # ->_frozen_set_is_checked
241             #
242             # Frozen implementation of set_is_checked().
243             #
244             sub _frozen_set_is_checked
245             {
246 24     24   22 my $this = shift;
247 24         22 my ($checked) = @_;
248              
249             #
250             # The first time we do this, save current status in `old_is_checked'.
251             #
252              
253 24 50       72 $this->{old_is_checked} = $this->{is_checked}
254             unless exists $this->{old_is_checked};
255 24         28 $this->{is_checked} = $checked;
256              
257 24         36 return;
258             }
259              
260             ############################################################
261             #
262             # ->_mark_by_tag
263             #
264             # Lookup the box in the group whose name is the given tag, and mark it
265             # as specified.
266             #
267             ############################################################
268             sub _mark_by_tag
269             {
270 6     6   12 my $this = shift;
271 6         10 my ($tag, $checked) = @_;
272              
273 6         48 my @boxes = grep {$_->value eq $tag} $this->group_list();
  18         40  
274              
275 6 50       26 if (@boxes == 0)
276             {
277 0         0 carp "no %s within the group '%s' bears the tag \"$tag\"",
278             $this->gui_type(), $this->name();
279             }
280             else
281             {
282 6 50       18 carp "found %d %ss within the group '%s' bearing the tag \"$tag\"",
283             scalar(@boxes), $this->gui_type(), $this->name()
284             if @boxes > 1;
285              
286 6         34 $boxes[ 0 ]->set_is_checked($checked);
287             }
288              
289 6         16 return;
290             }
291              
292             1;
293              
294             =head1 NAME
295              
296             CGI::Test::Form::Widget::Box - Abstract representation of a tickable box
297              
298             =head1 SYNOPSIS
299              
300             # Inherits from CGI::Test::Form::Widget
301              
302             =head1 DESCRIPTION
303              
304             This class is the abstract representation of a tickable box, i.e. a radio
305             button or a checkbox.
306              
307             To simulate user checking or un-checking on a box,
308             use the C and C routines, as described below.
309              
310             =head1 INTERFACE
311              
312             The interface is the same as the one described in L,
313             with the following additions:
314              
315             =head2 Attributes
316              
317             =over 4
318              
319             =item C
320              
321             The C object which holds all the groups of the same
322             widget type.
323              
324             =item C
325              
326             The list of widgets belonging to the same group as we do.
327              
328             =item C
329              
330             True when the box is checked, i.e. marked with a tick.
331              
332             =back
333              
334             =head2 Attribute Setting
335              
336             =over 4
337              
338             =item C
339              
340             Check the box, by ticking it.
341              
342             =item C I
343              
344             This may be called on any box, and it will locate the box whose value
345             attribute is I within the C, and then check it.
346              
347             If the specified I is not found, the caller will get a warning
348             via C.
349              
350             =item C
351              
352             Uncheck the box, by removing its ticking mark.
353             It is not possible to do this on a radio button: you must I another
354             radio button of the same group instead.
355              
356             =item C I
357              
358             This may be called on any box, and it will locate the box whose value
359             attribute is I within the C, and then remove its ticking mark.
360             It is not possible to do this on a radio button, as explained in C
361             above.
362              
363             If the specified I is not found, the caller will get a warning
364             via C.
365              
366             =back
367              
368             =head2 Widget Classification Predicates
369              
370             There is an additional predicate to distinguish between a checkbox and
371             a radio button:
372              
373             =over 4
374              
375             =item C
376              
377             Returns I for a radio button.
378              
379             =item C
380              
381             Returns I if the box is the sole member of its group.
382              
383             Normally only useful for checkboxes: a standalone radio button,
384             although perfectly legal, would always remain in the checked state, and
385             therefore not be especially interesting...
386              
387             =back
388              
389             =head2 Miscellaneous Features
390              
391             Although documented, those features are more targetted for
392             internal use...
393              
394             =over 4
395              
396             =item C I
397              
398             Change the checked status. Radio buttons can only be checked, i.e. the
399             I must be true: all other radio buttons in the same group are
400             immediately unchecked.
401              
402             You should use the C and C convenience routines instead
403             of calling this feature.
404              
405             =back
406              
407             =head1 AUTHORS
408              
409             The original author is Raphael Manfredi.
410              
411             Steven Hilton was long time maintainer of this module.
412              
413             Current maintainer is Alexander Tokarev Ftokarev@cpan.orgE>.
414              
415             =head1 SEE ALSO
416              
417             CGI::Test::Form::Widget(3),
418             CGI::Test::Form::Widget::Box::Radio(3),
419             CGI::Test::Form::Widget::Box::Check(3).
420              
421             =cut
422