File Coverage

blib/lib/HTML/FormHighlight.pm
Criterion Covered Total %
statement 9 73 12.3
branch 0 34 0.0
condition 0 50 0.0
subroutine 3 12 25.0
pod 2 2 100.0
total 14 171 8.1


line stmt bran cond sub pod time code
1             ################################################################################
2             # HTML::FormHighlight
3             #
4             # A module used to highlight fields in an HTML form.
5             #
6             # Author: Adekunle Olonoh
7             # Date: March 2001
8             ################################################################################
9              
10              
11             package HTML::FormHighlight;
12              
13              
14             ################################################################################
15             # - Modules and Libraries
16             ################################################################################
17 1     1   684 use strict;
  1         2  
  1         25  
18 1     1   5 use Carp;
  1         1  
  1         74  
19 1     1   877 use HTML::Parser;
  1         5805  
  1         1097  
20              
21              
22              
23             ################################################################################
24             # - Global Constants and Variables
25             ################################################################################
26             $HTML::FormHighlight::VERSION = '0.03';
27              
28              
29             ################################################################################
30             # - Subroutines
31             ################################################################################
32              
33              
34             ################################################################################
35             # new()
36             ################################################################################
37             sub new {
38 0     0 1   my ($proto, %options) = @_;
39            
40 0   0       my $class = ref($proto) || $proto;
41            
42 0           my $self = bless {}, $class;
43            
44 0           return $self;
45             }
46              
47              
48             ################################################################################
49             # highlight()
50             ################################################################################
51             sub highlight {
52 0     0 1   my ($self, %options) = @_;
53            
54             # Initialize the fields option with a blank array ref
55 0   0       $options{'fields'} ||= [];
56            
57             # Buld a hash containing each of the field names pointing to a true value
58 0           $self->{'fields'} = { map { $_ => 1 } @{$options{'fields'}} };
  0            
  0            
59            
60             # Initialize fields with parameters or defaults
61 0   0       $self->{'highlight'} = $options{'highlight'} || '*';
62 0   0       $self->{'mark'} = $options{'mark'} || '';
63 0   0       $self->{'all_in_group'} = $options{'all_in_group'} || 0;
64            
65             # Initialize private variables
66 0           $self->{'_output'} = '';
67 0           $self->{'_highlighted'} = {};
68 0           $self->{'_field_filled'} = {};
69 0           $self->{'_buffer'} = '';
70            
71             # Create a regular expression for mark replacement
72 0           $self->{'_mark_regex'} = qr/^(.*)($self->{'mark'})((?!$self->{'mark'}).*)$/s;
73            
74             # Check for a CGI.pm (or equivalent) object
75 0 0         if ($options{'fobject'}) {
76             # Die if the param() method isn't defined for the form object
77 0 0         croak('HTML::FormHighlight->highlight called with fobject option, containing object of type '.ref($options{'fobject'}).' which lacks a param() method.') unless defined($options{'fobject'}->can('param'));
78              
79             # Iterate over each form value
80 0           foreach my $key ($options{'fobject'}->param()) {
81             # Indicate that the field has been filled in if it contains a true value
82 0 0         $self->{'_field_filled'}->{$key} = 1 if $options{'fobject'}->param($key);
83             }
84             }
85            
86             # Check for a hash reference containing form data
87 0 0         if ($options{'fdat'}){
88             # Iterate over each key
89 0           foreach my $key (keys %{$options{'fdat'}}) {
  0            
90             # Indicate that the field has been filled in if it contains a true value
91 0 0         $self->{'_field_filled'}->{$key} = 1 if $options{'fdat'}->{$key};
92             }
93             }
94            
95              
96             # Create a new HTML::Parser object
97             my $parser = HTML::Parser->new(
98             api_version => 3,
99 0     0     start_h => [ sub { _start($self, @_) }, 'tagname, attr, text' ],
100 0     0     end_h => [ sub { _end($self, @_) }, 'tagname, text' ],
101 0     0     default_h => [ sub { _default($self, @_) }, 'text' ],
  0            
102             );
103            
104            
105             # Check for the parse method, and use HTML::Parser appropriately
106 0 0         if ($options{'file'}) {
    0          
    0          
107             # Parse from file
108 0           $parser->parse_file($options{'file'});
109             }
110             elsif ($options{'scalarref'}) {
111             # Parse from scalar reference
112 0           $parser->parse(${$options{'scalarref'}});
  0            
113             }
114             elsif ($options{'arrayref'}) {
115             # Parse from array reference, iterating over each line
116 0           for (@{$options{'arrayref'}}) {
  0            
117 0           $parser->parse($_);
118             }
119             }
120              
121             # Signal EOF to HTML::Parser
122 0           $parser->eof();
123            
124             # Append the last of the buffered text to the output variable
125 0           $self->{'_output'} .= $self->{'_buffer'};
126 0           $self->{'_buffer'} = undef;
127            
128             # Return the generated output
129 0           return $self->{'_output'};
130             }
131              
132              
133             ################################################################################
134             # _start()
135             ################################################################################
136             sub _start {
137 0     0     my($self, $tagname, $attr, $origtext) = @_;
138            
139             # Check to make sure the current tag is a form field
140 0 0 0       if (
      0        
      0        
141             ($tagname eq 'input') or
142             ($tagname eq 'textarea') or
143             ($tagname eq 'select') or
144             ($tagname eq 'option')
145             ){
146            
147             # Make sure the field has a name and that the field wasn't filled in
148 0 0 0       if ($self->{'fields'}->{$attr->{'name'}} and !$self->{'_field_filled'}->{$attr->{'name'}}) {
149            
150             # Check for all input tags
151 0 0 0       if ($tagname eq 'input') {
    0          
152            
153             # Check for text, password and file tags
154 0 0 0       if (($attr->{'type'} eq 'text') or ($attr->{'type'} eq 'password') or ($attr->{'type'} eq 'file')) {
    0 0        
      0        
155            
156             # Insert the highlight
157 0           $self->_insert_highlight();
158             }
159             # Check for radio and checkbox tags
160             elsif (($attr->{'type'} eq 'radio') or ($attr->{'type'} eq 'checkbox')) {
161            
162             # Check if all options in a group should be highlighted,
163             # or if an option in the group hasn't already been highlighted
164 0 0 0       if ($self->{'all_in_group'} or (!$self->{'_highlighted'}->{$attr->{'name'}})) {
165            
166             # Insert the highlight
167 0           $self->_insert_highlight();
168              
169             # Indicate that an option in the group has been highlighted
170 0           $self->{'_highlighted'}->{$attr->{'name'}} = 1;
171             }
172             }
173             }
174             # Check for textarea or select tags
175             elsif (($tagname eq 'textarea') or ($tagname eq 'select')) {
176             # Insert the highlight
177 0           $self->_insert_highlight();
178             }
179             }
180            
181             # Add the buffer and original text to output
182 0           $self->{'_output'} .= $self->{'_buffer'}.$origtext;
183            
184             # Clear the buffer
185 0           $self->{'_buffer'} = '';
186             }
187             else {
188             # Add the original text to the buffer
189 0           $self->{'_buffer'} .= $origtext;
190             }
191             }
192              
193              
194             ################################################################################
195             # _end()
196             ################################################################################
197             sub _end {
198 0     0     my($self, $tagname, $origtext) = @_;
199            
200             # Check if the current tag is a form tag
201 0 0 0       if (
      0        
202             ($tagname eq 'textarea') or
203             ($tagname eq 'select') or
204             ($tagname eq 'option')
205             ){
206             # Add the buffer and original text to output
207 0           $self->{'_output'} .= $self->{'_buffer'}.$origtext;
208            
209             # Clear the buffer
210 0           $self->{'_buffer'} = '';
211             }
212             else {
213             # Add the original text to the buffer
214 0           $self->{'_buffer'} .= $origtext;
215             }
216             }
217              
218              
219             ################################################################################
220             # _default()
221             ################################################################################
222             sub _default {
223 0     0     my($self, $origtext) = @_;
224            
225             # Add the original text to the buffer
226 0           $self->{'_buffer'} .= $origtext;
227             }
228              
229              
230             ################################################################################
231             # _insert_highlight()
232             ################################################################################
233             sub _insert_highlight {
234 0     0     my $self = shift;
235            
236             # Check to make sure the buffer and mark exist, and that the buffer contains the mark
237 0 0 0       if (($self->{'_buffer'}) and ($self->{'mark'}) and ($self->{'_buffer'} =~ $self->{'_mark_regex'})) {
      0        
238             # Replace the last occurence of the mark with the highlight
239 0           $self->{'_buffer'} =~ s/$self->{'_mark_regex'}/$1$2$self->{'highlight'}$3/;
240             }
241             else {
242             # Just append the highlight to the buffer
243 0           $self->{'_buffer'} .= $self->{'highlight'};
244             }
245             }
246              
247              
248             1;
249              
250              
251             =head1 NAME
252              
253             HTML::FormHighlight - Highlights fields in an HTML form.
254              
255              
256             =head1 SYNOPSIS
257              
258             use HTML::FormHighlight;
259              
260             my $h = new HTML::FormHighlight;
261            
262             print $h->highlight(
263             scalarref => \$form,
264             fields => [ 'A', 'B', 'C' ],
265             );
266            
267             print $h->highlight(
268             scalarref => \$form,
269             fields => [ 'A', 'B', 'C' ],
270             highlight => '*',
271             mark => '',
272             all_in_group => 1,
273             );
274            
275              
276             =head1 DESCRIPTION
277              
278             HTML::FormHighlight can be used to highlight fields in an HTML form. It uses HTML::Parser to parse the HTML form, and then places text somewhere before each field to highlight the field. You can specify which fields to highlight, and optionally supply a CGI object for it to check whether or not an input value exists before highlighting the field.
279              
280             It can be used when displaying forms where a user hasn't filled out a required field. The indicator can make it easier for a user to locate the fields that they've missed. If you're interested in more advanced form validation, see L. L can also be used to fill form fields with values that have already been submitted.
281              
282             =head1 METHODS
283              
284              
285             =head2 new()
286              
287             Create a new HTML::FormHighlight object. Example:
288            
289             $h = new HTML::FormHighlight;
290              
291            
292             =head2 highlight()
293              
294             Parse through the HTML form and highlight fields. The method returns a scalar containing the parsed form. Here are a few examples:
295              
296             To highlight the fields 'A', 'B' and 'C' (form on disk):
297            
298             $h->highlight(
299             file => 'form.html',
300             fields => [ 'A', 'B', 'C' ],
301             );
302            
303             To highlight the fields 'A' and 'B' with a smiley face
304             (form as a scalar):
305            
306             $h->highlight(
307             scalarref => \$form,
308             fields => [ 'A', 'B' ],
309             highlight => '',
310             );
311            
312             To highlight the fields 'A' and 'B' if they haven't been supplied
313             by form input (form as an array of lines):
314            
315             $q = new CGI;
316            
317             $h->highlight(
318             arrayref => \@form,
319             fields => [ 'A', 'B' ],
320             fobject => $q,
321             );
322            
323             Note: highlight() will only highlight the first option in a radio or select group unless the all_in_group flag is set to a true value.
324            
325             Here's a list of possible parameters for highlight() and their descriptions:
326              
327             =over 4
328              
329             =item *
330              
331             scalarref - a reference to a scalar that contains the text of the form.
332              
333             =item *
334              
335             arrayref - a reference to an array of lines that contain the text of the form.
336              
337             =item *
338              
339             file - a scalar that contains the file name where the form is kept.
340              
341             =item *
342              
343             fields - a reference to an array that lists the fields to be highlighted. If used in conjunction with "fobject" or "fdat", only the fields listed that are empty will be highlighted.
344              
345             =item *
346              
347             highlight - a scalar that contains the highlight indicator. Defaults to a red asterisk (*).
348              
349             =item *
350              
351             mark - a regex specifying where to place the highlight indicator. If this is empty, the indicator will be inserted directly before the form field. The HTML form does not need to contain the text specified in the regex before each form field. highlight() will only use a mark for a field if there is no other form field before the field it's highlighting. If there is more than one mark before a field, it will only highlight the last mark. If it doesn't find a mark, it will insert the indicator directly before the form field. Here are a few examples:
352              
353             code:
354             =====
355            
356             $h->highlight(
357             file => 'form.html',
358             fields => [ 'A', 'B', 'C' ],
359             mark => ''
360             highlight => '***',
361             );
362            
363            
364             input:
365             ======
366            
367            
368             Field B:
369            
370            
371             output:
372             =======
373            
374             ***
375             *** Field B:
376             ***
377            
378            
379             input:
380             ======
381            
382             Field A:
383             Field B:
384             Field C:
385            
386            
387            
388            
389             output:
390             =======
391            
392             Field A: ***
393             Field B: ***
394             Field C:
395            
396             ***
397            
398            
399            
400             input:
401             ======
402            
403             Field A:
404            
Foo...
405            
Bar...
406            
407            
408             Field B:
409            
410            
411             Field C:
412            
413            
414            
415            
416            
417             output:
418             =======
419            
420             Field A:
421            
Foo...
422             ***
Bar...
423            
424            
425             Field B:
426             ***
427            
428             Field C:
429            
430            
431             ***
432            
433            
434            
435             Warning: Since the mark field is a regular expression, make sure to escape it appropriately. "\s" will insert the highlight after the last space character. To replace all occurrences of a backslash followed by the letter s, use "\\\s".
436              
437             =item *
438              
439             all_in_group - set this to 1 if you want all options in a radio or checkbox group to be highlighted. It's set to 0 by default.
440              
441             =item *
442              
443             fobject - a CGI.pm object, or another object which has a param() method that works like CGI.pm's. HTML::FormHighlight will check to see if a parameter does not have a value before highlighting the field.
444              
445             =item *
446              
447             fdat - a hash reference, with the field names as keys. HTML::FormHighlight will check to see if a parameter does not have a value before highlighting the field.
448              
449             =back 4
450              
451             =head1 BUGS
452              
453             =over 4
454              
455             =item *
456              
457             highlight() will add the highlight indicator inside an HTML tag if you're not careful.
458              
459             For example, if you use "\s" as your mark and "***" as your indicator,
460              
461             A:
462            
463             will result in:
464            
465             A:
466            
467             not:
468            
469             A: ***
470            
471             =back 4
472              
473              
474             =head1 VERSION
475              
476             0.03
477              
478             =head1 AUTHOR
479              
480             Adekunle Olonoh, ade@bottledsoftware.com
481              
482             =head1 CREDITS
483              
484             Hiroki Chalfant
485              
486             =head1 COPYRIGHT
487              
488             Copyright (c) 2000 Adekunle Olonoh. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
489              
490             =head1 SEE ALSO
491              
492             L, L, L, L
493              
494             =cut