File Coverage

blib/lib/HTML/TagCloud.pm
Criterion Covered Total %
statement 104 127 81.8
branch 26 36 72.2
condition 2 6 33.3
subroutine 16 19 84.2
pod 9 9 100.0
total 157 197 79.7


line stmt bran cond sub pod time code
1             package HTML::TagCloud;
2 1     1   894 use strict;
  1         3  
  1         45  
3 1     1   6 use warnings;
  1         3  
  1         71  
4             our $VERSION = '0.38';
5              
6 1     1   6 use constant EMPTY_STRING => q{};
  1         2  
  1         1535  
7              
8             sub new {
9 9     9 1 5769 my $class = shift;
10 9         54 my $self = {
11             counts => {},
12             urls => {},
13             category_for => {},
14             categories => [],
15             levels => 24,
16             distinguish_adjacent_tags => 0,
17             @_
18             };
19 9         26 bless $self, $class;
20 9         19 return $self;
21             }
22              
23             sub add {
24 359     359 1 2846 my ( $self, $tag, $url, $count, $category ) = @_;
25 359         572 $self->{counts}->{$tag} = $count;
26 359         527 $self->{urls}->{$tag} = $url;
27 359 50 33     305 if ( scalar @{ $self->{categories} } > 0 && defined $category ) {
  359         987  
28 0         0 $self->{category_for}->{$tag} = $category;
29             }
30             }
31              
32             sub add_static {
33 10     10 1 49 my ( $self, $tag, $count, $category ) = @_;
34 10         22 $self->{counts}->{$tag} = $count;
35              
36 10 50 33     10 if ( scalar @{ $self->{categories} } > 0 && defined $category ) {
  10         43  
37 0         0 $self->{category_for}->{$tag} = $category;
38             }
39             }
40              
41             sub css {
42 3     3 1 30 my ($self) = @_;
43 3         7 my $css = q(
44             #htmltagcloud {
45             text-align: center;
46             line-height: 1;
47             }
48             );
49 3         11 foreach my $level ( 0 .. $self->{levels} ) {
50 75 100       137 if ( $self->{distinguish_adjacent_tags} ) {
51 25         43 $css .= $self->_css_for_tag( $level, 'even' );
52 25         42 $css .= $self->_css_for_tag( $level, 'odd' );
53             }
54             else {
55 50         78 $css .= $self->_css_for_tag( $level, q{} );
56             }
57             }
58 3         27 return $css;
59             }
60              
61             sub _css_for_tag {
62 100     100   127 my ( $self, $level, $subclass ) = @_;
63 100         113 my $font = 12 + $level;
64 100         313 return <<"END_OF_TAG";
65             span.tagcloud${level}${subclass} {font-size: ${font}px;}
66             span.tagcloud${level}${subclass} a {text-decoration: none;}
67             END_OF_TAG
68             }
69              
70             sub tags {
71 15     15 1 17 my ( $self, $limit ) = @_;
72 15         28 my $counts = $self->{counts};
73 15         21 my $urls = $self->{urls};
74 15         22 my $category_for = $self->{category_for};
75 15 50       309 my @tags = sort { $counts->{$b} <=> $counts->{$a} || $a cmp $b } keys %$counts;
  17732         34295  
76 15 100       205 @tags = splice( @tags, 0, $limit ) if defined $limit;
77              
78 15 100       40 return unless scalar @tags;
79              
80 14         62 my $min = log( $counts->{ $tags[-1] } );
81 14         30 my $max = log( $counts->{ $tags[0] } );
82 14         16 my $factor;
83              
84             # special case all tags having the same count
85 14 100       45 if ( $max - $min == 0 ) {
86 9         14 $min = $min - $self->{levels};
87 9         12 $factor = 1;
88             }
89             else {
90 5         15 $factor = $self->{levels} / ( $max - $min );
91             }
92              
93 14 100       36 if ( scalar @tags < $self->{levels} ) {
94 13         28 $factor *= ( scalar @tags / $self->{levels} );
95             }
96 14         18 my @tag_items;
97 14         160 foreach my $tag ( sort @tags ) {
98 402         358 my $tag_item;
99 402         657 $tag_item->{name} = $tag;
100 402         526 $tag_item->{count} = $counts->{$tag};
101 402         604 $tag_item->{url} = $urls->{$tag};
102 402         797 $tag_item->{level}
103             = int( ( log( $tag_item->{count} ) - $min ) * $factor );
104 402         476 $tag_item->{category} = $category_for->{$tag};
105 402         578 push @tag_items, $tag_item;
106             }
107 14         168 return @tag_items;
108             }
109              
110             sub html {
111 15     15 1 4902 my ( $self, $limit ) = @_;
112 15         60 my $html
113 15 50       17 = scalar @{ $self->{categories} } > 0
114             ? $self->html_with_categories($limit)
115             : $self->html_without_categories($limit);
116 15         257 return $html;
117             }
118              
119             sub html_without_categories {
120 15     15 1 20 my ( $self, $limit ) = @_;
121 15         31 my $html = $self->_html_for( [ $self->tags($limit) ] );
122             }
123              
124             sub _html_for {
125 15     15   21 my ( $self, $tags_ref ) = @_;
126 15         22 my $ntags = scalar( @{$tags_ref} );
  15         19  
127 15 100       43 return EMPTY_STRING if $ntags == 0;
128              
129             # Format the HTML division.
130 14 100       72 my $html
131             = $ntags == 1
132             ? $self->_html_for_single_tag($tags_ref)
133             : $self->_html_for_multiple_tags($tags_ref);
134              
135 14         38 return $html;
136             }
137              
138             sub _html_for_single_tag {
139 3     3   6 my ( $self, $tags_ref ) = @_;
140              
141             # Format the contents of the div.
142 3         4 my $tag_ref = $tags_ref->[0];
143 3         7 my $html = $self->_format_span( @{$tag_ref}{qw(name url)}, 1, 1 );
  3         12  
144              
145 3         10 return qq{
$html
\n};
146             }
147              
148             sub _html_for_multiple_tags {
149 11     11   17 my ( $self, $tags_ref ) = @_;
150              
151             # Format the contents of the div.
152 11         16 my $html = EMPTY_STRING;
153 11         12 my $is_even = 1;
154 11         24 foreach my $tag ( @{$tags_ref} ) {
  11         20  
155 399         1030 my $span
156 399         429 = $self->_format_span( @{$tag}{qw(name url level)}, $is_even );
157 399         788 $html .= "$span\n";
158 399         574 $is_even = !$is_even;
159             }
160 11         66 $html = qq{
161             $html};
162 11         56 return $html;
163             }
164              
165             sub html_with_categories {
166 0     0 1 0 my ( $self, $limit ) = @_;
167              
168             # Get the collection of tags, organized by category.
169 0         0 my $tags_by_category_ref = $self->_tags_by_category($limit);
170 0 0       0 return EMPTY_STRING if !defined $tags_by_category_ref;
171              
172             # Format the HTML document.
173 0         0 my $html = EMPTY_STRING;
174 0         0 CATEGORY:
175 0         0 for my $category ( @{ $self->{categories} } ) {
176 0         0 my $tags_ref = $tags_by_category_ref->{$category};
177 0         0 $html .= $self->_html_for_category( $category, $tags_ref );
178             }
179              
180 0         0 return $html;
181             }
182              
183             sub _html_for_category {
184 0     0   0 my ( $self, $category, $tags_ref ) = @_;
185              
186             # Format the HTML.
187 0         0 my $html
188             = qq{
}
189             . $self->_html_for($tags_ref)
190             . qq{};
191              
192 0         0 return $html;
193             }
194              
195             sub _tags_by_category {
196 0     0   0 my ( $self, $limit ) = @_;
197              
198             # Get the tags.
199 0         0 my @tags = $self->tags($limit);
200 0 0       0 return if scalar @tags == 0;
201              
202             # Build the categorized collection of tags.
203 0         0 my %tags_by_category;
204 0         0 for my $tag_ref (@tags) {
205 0 0       0 my $category
206             = defined $tag_ref->{category}
207             ? $tag_ref->{category}
208             : '__unknown__';
209 0         0 push @{ $tags_by_category{$category} }, $tag_ref;
  0         0  
210             }
211              
212 0         0 return \%tags_by_category;
213             }
214              
215             sub html_and_css {
216 1     1 1 1233 my ( $self, $limit ) = @_;
217 1         6 my $html = qq{";
218 1         3 $html .= $self->html($limit);
219 1         8 return $html;
220             }
221              
222             sub _format_span {
223 402     402   613 my ( $self, $name, $url, $level, $is_even ) = @_;
224 402         469 my $subclass = q{};
225 402 100       783 if ( $self->{distinguish_adjacent_tags} ) {
226 10 100       22 $subclass = $is_even ? 'even' : 'odd';
227             }
228 402         610 my $span_class = qq{tagcloud$level$subclass};
229 402         1597 my $span = qq{};
230 402 100       770 if ( defined $url ) {
231 392         705 $span .= qq{};
232             }
233 402         447 $span .= $name;
234 402 100       687 if ( defined $url ) {
235 392         438 $span .= qq{};
236             }
237 402         803 $span .= qq{};
238             }
239              
240             1;
241              
242             __END__