File Coverage

blib/lib/Tags/HTML/Pager.pm
Criterion Covered Total %
statement 77 87 88.5
branch 31 44 70.4
condition 12 21 57.1
subroutine 12 12 100.0
pod 1 1 100.0
total 133 165 80.6


line stmt bran cond sub pod time code
1             package Tags::HTML::Pager;
2              
3 5     5   112978 use base qw(Tags::HTML);
  5         42  
  5         2199  
4 5     5   88444 use strict;
  5         8  
  5         78  
5 5     5   19 use warnings;
  5         9  
  5         109  
6              
7 5     5   33 use Class::Utils qw(set_params split_params);
  5         7  
  5         173  
8 5     5   22 use Error::Pure qw(err);
  5         7  
  5         124  
9 5     5   20 use Readonly;
  5         14  
  5         173  
10 5     5   1968 use Unicode::UTF8 qw(decode_utf8);
  5         1946  
  5         6113  
11              
12             Readonly::Scalar our $NUMBER_OF_BOXES => 7;
13              
14             our $VERSION = 0.04;
15              
16             # Constructor.
17             sub new {
18 16     16 1 17181 my ($class, @params) = @_;
19              
20             # Create object.
21 16         66 my ($object_params_ar, $other_params_ar) = split_params(
22             ['css_colors', 'css_pager', 'flag_prev_next', 'flag_paginator',
23             'url_page_cb'], @params);
24 16         523 my $self = $class->SUPER::new(@{$other_params_ar});
  16         52  
25              
26             # CSS colors.
27             $self->{'css_colors'} = {
28             'actual_background' => 'black',
29             'actual_color' => 'white',
30             'border' => 'black',
31             'hover_background' => 'black',
32             'hover_color' => 'white',
33             'other_background' => undef,
34             'other_color' => 'black',
35             },
36              
37             # CSS class.
38 14         383 $self->{'css_pager'} = 'pager';
39              
40             # Flag for prev/next buttons.
41 14         21 $self->{'flag_prev_next'} = 0;
42              
43             # Flag for paginator.
44 14         23 $self->{'flag_paginator'} = 1;
45              
46             # URL of page.
47 14         29 $self->{'url_page_cb'} = undef;
48              
49             # Process params.
50 14         18 set_params($self, @{$object_params_ar});
  14         33  
51              
52 14 100       169 if (! defined $self->{'css_pager'}) {
53 1         3 err "Parameter 'css_pager' is required.";
54             }
55              
56 13 100       26 if (! defined $self->{'url_page_cb'}) {
57 1         4 err "Missing 'url_page_cb' parameter.";
58             }
59              
60 12 100 100     33 if (! $self->{'flag_paginator'} && ! $self->{'flag_prev_next'}) {
61 1         4 err 'Both paginator styles disabled.';
62             }
63              
64             # Object.
65 11         102 return $self;
66             }
67              
68             sub _process {
69 7     7   65 my ($self, $pages_hr) = @_;
70              
71 7 100       15 if (! $pages_hr) {
72 1         4 err 'Pages data structure is missing.';
73             }
74 6 100       11 if (! exists $pages_hr->{'pages_num'}) {
75 1         3 err "Missing 'pages_num' parameter in pages data structure.";
76             }
77 5 100       11 if (! exists $pages_hr->{'actual_page'}) {
78 1         3 err "Missing 'actual_page' parameter in pages data structure.";
79             }
80 4 100       10 if ($pages_hr->{'actual_page'} > $pages_hr->{'pages_num'}) {
81             err "Parameter 'actual_page' is greater than parameter 'pages_num'.",
82             'actual_page', $pages_hr->{'actual_page'},
83 1         4 'pages_num', $pages_hr->{'pages_num'},
84             ;
85             }
86              
87             # No code.
88 3 100 66     15 if (! $self->{'flag_paginator'}
      66        
89             && $self->{'flag_prev_next'} && $pages_hr->{'pages_num'} == 1) {
90              
91 1         3 return;
92             }
93              
94             $self->{'tags'}->put(
95             ['b', 'div'],
96 2         11 ['a', 'class', $self->{'css_pager'}],
97             );
98              
99             # Paginator
100 2 100       130 if ($self->{'flag_paginator'}) {
101 1         5 $self->{'tags'}->put(
102             ['b', 'p'],
103             ['a', 'class', $self->_css_class('paginator')],
104             );
105 1         49 my $buttons_from = 1;
106 1         2 my $buttons_to = $pages_hr->{'pages_num'};
107 1 50 33     4 if ($pages_hr->{'actual_page'} > 4
108             && $pages_hr->{'pages_num'} > $NUMBER_OF_BOXES) {
109              
110             $self->{'tags'}->put(
111             ['b', 'a'],
112 0         0 ['a', 'href', $self->{'url_page_cb'}->(1)],
113             ['d', 1],
114             ['e', 'a'],
115              
116             ['b', 'span'],
117             ['d', decode_utf8('…')],
118             ['e', 'span'],
119             );
120 0 0       0 if ($pages_hr->{'actual_page'} < $pages_hr->{'pages_num'} - 3) {
121 0         0 $buttons_from = $pages_hr->{'actual_page'} - 1;
122             } else {
123 0         0 $buttons_from = $pages_hr->{'pages_num'} - 4;
124             }
125             }
126 1 50 33     5 if ($pages_hr->{'actual_page'} < $pages_hr->{'pages_num'} - 3
127             && $pages_hr->{'pages_num'} > $NUMBER_OF_BOXES) {
128              
129 0 0       0 if ($pages_hr->{'actual_page'} > 4) {
130 0         0 $buttons_to = $pages_hr->{'actual_page'} + 1;
131             } else {
132 0         0 $buttons_to = 5;
133             }
134             }
135 1         4 foreach my $button_num ($buttons_from .. $buttons_to) {
136 1 50       4 if ($pages_hr->{'actual_page'} eq $button_num) {
137 1         5 $self->{'tags'}->put(
138             ['b', 'strong'],
139             ['a', 'class', $self->_css_class('paginator-selected')],
140             ['d', $button_num],
141             ['e', 'strong'],
142             );
143             } else {
144             $self->{'tags'}->put(
145             ['b', 'a'],
146 0         0 ['a', 'href', $self->{'url_page_cb'}->($button_num)],
147             ['d', $button_num],
148             ['e', 'a'],
149             );
150             }
151             }
152 1 50 33     107 if ($pages_hr->{'actual_page'} < $pages_hr->{'pages_num'} - 3
153             && $pages_hr->{'pages_num'} > $NUMBER_OF_BOXES) {
154              
155             $self->{'tags'}->put(
156             ['b', 'span'],
157             ['d', decode_utf8('…')],
158             ['e', 'span'],
159              
160             ['b', 'a'],
161             ['a', 'href', $self->{'url_page_cb'}->($pages_hr->{'pages_num'})],
162 0         0 ['d', $pages_hr->{'pages_num'}],
163             ['e', 'a'],
164             );
165             }
166 1         5 $self->{'tags'}->put(
167             ['e', 'p'],
168             );
169             }
170              
171             # Paging.
172 2 100 66     36 if ($self->{'flag_prev_next'} && $pages_hr->{'pages_num'} > 1) {
173 1         3 my ($prev, $next);
174 1 50       4 if ($pages_hr->{'pages_num'} > 1) {
175 1 50       2 if ($pages_hr->{'actual_page'} > 1) {
176 0         0 $prev = $pages_hr->{'actual_page'} - 1;
177             }
178 1 50       5 if ($pages_hr->{'actual_page'} < $pages_hr->{'pages_num'}) {
179 1         2 $next = $pages_hr->{'actual_page'} + 1;
180             }
181             }
182            
183             $self->{'tags'}->put(
184             ['b', 'p'],
185             ['a', 'class', $self->_css_class('prev_next')],
186              
187             # Previous page.
188             $prev ? (
189             ['b', 'a'],
190             ['a', 'class', $self->_css_class('prev')],
191             ['a', 'href', $self->{'url_page_cb'}->($prev)],
192             ['d', decode_utf8('←')],
193             ['e', 'a'],
194             ) : (
195             ['b', 'span'],
196             ['a', 'class', $self->_css_class('prev-disabled')],
197             ['d', decode_utf8('←')],
198             ['e', 'span'],
199             ),
200              
201             # Next page.
202             $next ? (
203             ['b', 'a'],
204             ['a', 'class', $self->_css_class('next')],
205 1 50       4 ['a', 'href', $self->{'url_page_cb'}->($next)],
    50          
206             ['d', decode_utf8('→')],
207             ['e', 'a'],
208             ) : (
209             ['b', 'span'],
210             ['a', 'class', $self->_css_class('next-disabled')],
211             ['d', decode_utf8('→')],
212             ['e', 'span'],
213             ),
214              
215             ['e', 'p'],
216             );
217             }
218              
219 2         277 $self->{'tags'}->put(
220             ['e', 'div'],
221             );
222              
223 2         58 return;
224             }
225              
226             sub _process_css {
227 1     1   12 my $self = shift;
228              
229             $self->{'css'}->put(
230             ['s', '.'.$self->{'css_pager'}.' a'],
231             ['d', 'text-decoration', 'none'],
232             ['e'],
233              
234             ['s', '.'.$self->_css_class('paginator')],
235             ['d', 'display', 'flex'],
236             ['d', 'flex-wrap', 'wrap'],
237             ['d', 'justify-content', 'center'],
238             ['d', 'padding-left', '130px'],
239             ['d', 'padding-right', '130px'],
240             ['d', 'float', 'both'],
241             ['e'],
242              
243             ['s', '.'.$self->_css_class('prev_next')],
244             ['d', 'display', 'flex'],
245             ['e'],
246              
247             ['s', '.'.$self->_css_class('paginator').' a'],
248             ['s', '.'.$self->_css_class('paginator').' strong'],
249             ['s', '.'.$self->_css_class('paginator').' span'],
250             ['s', '.'.$self->_css_class('next')],
251             ['s', '.'.$self->_css_class('next-disabled')],
252             ['s', '.'.$self->_css_class('prev')],
253             ['s', '.'.$self->_css_class('prev-disabled')],
254             ['d', 'display', 'flex'],
255             ['d', 'height', '55px'],
256             ['d', 'width', '55px'],
257             ['d', 'justify-content', 'center'],
258             ['d', 'align-items', 'center'],
259             ['d', 'border', '1px solid '.$self->{'css_colors'}->{'border'}],
260             ['d', 'margin-left', '-1px'],
261             ['e'],
262              
263              
264             ['s', '.'.$self->_css_class('prev')],
265             ['s', '.'.$self->_css_class('next')],
266             ['d', 'display', 'inline-flex'],
267             ['d', 'align-items', 'center'],
268             ['d', 'justify-content', 'center'],
269             ['e'],
270              
271             ['s', '.'.$self->_css_class('paginator').' a:hover'],
272             ['s', '.'.$self->_css_class('prev_next').' a:hover'],
273             $self->_css_colors_optional('hover_color', 'color'),
274             $self->_css_colors_optional('hover_background', 'background-color'),
275             ['e'],
276              
277             ['s', '.'.$self->_css_class('paginator').' a'],
278             $self->_css_colors_optional('other_color', 'color'),
279             $self->_css_colors_optional('other_background', 'background-color'),
280             ['e'],
281              
282             ['s', '.'.$self->_css_class('paginator-selected')],
283             ['d', 'background-color', $self->{'css_colors'}->{'actual_background'}],
284 1         7 ['d', 'color', $self->{'css_colors'}->{'actual_color'}],
285             ['e'],
286             );
287              
288 1         978 return;
289             }
290              
291             sub _css_class {
292 20     20   33 my ($self, $suffix) = @_;
293              
294 20         144 return $self->{'css_pager'}.'-'.$suffix;
295             }
296              
297             sub _css_colors_optional {
298 4     4   7 my ($self, $css_color, $css_key) = @_;
299              
300             return defined $self->{'css_colors'}->{$css_color}
301 4 100       15 ? (['d', $css_key, $self->{'css_colors'}->{$css_color}])
302             : ();
303             }
304              
305             1;
306              
307             __END__