File Coverage

blib/lib/Tags/HTML/Image/Grid.pm
Criterion Covered Total %
statement 47 96 48.9
branch 2 34 5.8
condition 2 14 14.2
subroutine 10 13 76.9
pod 1 1 100.0
total 62 158 39.2


line stmt bran cond sub pod time code
1             package Tags::HTML::Image::Grid;
2              
3 3     3   84739 use base qw(Tags::HTML);
  3         21  
  3         1553  
4 3     3   84052 use strict;
  3         9  
  3         55  
5 3     3   15 use warnings;
  3         5  
  3         83  
6              
7 3     3   22 use Class::Utils qw(set_params split_params);
  3         14  
  3         122  
8 3     3   22 use Error::Pure qw(err);
  3         7  
  3         101  
9 3     3   22 use List::MoreUtils qw(none);
  3         9  
  3         13  
10 3     3   2018 use Scalar::Util qw(blessed);
  3         6  
  3         142  
11 3     3   1400 use Unicode::UTF8 qw(decode_utf8);
  3         1369  
  3         3972  
12              
13             our $VERSION = 0.03;
14              
15             # Constructor.
16             sub new {
17 5     5 1 6073 my ($class, @params) = @_;
18              
19             # Create object.
20 5         30 my ($object_params_ar, $other_params_ar) = split_params(
21             ['css_image_grid', 'img_border_color_cb', 'img_border_width', 'img_link_cb',
22             'img_select_cb', 'img_src_cb', 'img_width', 'title'], @params);
23 5         125 my $self = $class->SUPER::new(@{$other_params_ar});
  5         22  
24              
25             # Form CSS style.
26 5         123 $self->{'css_image_grid'} = 'image-grid';
27              
28             # Image border color callback.
29 5         10 $self->{'img_border_color_cb'} = undef;
30              
31             # Image border width (in pixels).
32 5         11 $self->{'img_border_width'} = undef;
33              
34             # Image link callback.
35 5         8 $self->{'img_link_cb'} = undef;
36              
37             # Image select callback.
38 5         15 $self->{'img_select_cb'} = undef;
39              
40             # Image src callback across data object.
41 5         8 $self->{'img_src_cb'} = undef;
42              
43             # Image width in pixels.
44 5         10 $self->{'img_width'} = 340;
45              
46             # Image grid title.
47 5         28 $self->{'title'} = undef;
48              
49             # Process params.
50 5         12 set_params($self, @{$object_params_ar});
  5         13  
51              
52             # Check callback codes.
53 5         88 $self->_check_callback('img_border_color_cb');
54 5         14 $self->_check_callback('img_link_cb');
55 4         12 $self->_check_callback('img_select_cb');
56 3         7 $self->_check_callback('img_src_cb');
57              
58             # Object.
59 2         12 return $self;
60             }
61              
62             sub _check_callback {
63 17     17   30 my ($self, $callback_key) = @_;
64              
65 17 100 66     52 if (defined $self->{$callback_key}
66             && ref $self->{$callback_key} ne 'CODE') {
67              
68 3         17 err "Parameter '$callback_key' must be a code.";
69             }
70              
71 14         18 return;
72             }
73              
74             sub _check_images {
75 0     0     my ($self, $images_ar) = @_;
76              
77 0           foreach my $image (@{$images_ar}) {
  0            
78 0 0 0       if (! blessed($image) && ! $image->isa('Data::Image')) {
79              
80 0           err 'Bad data image object.';
81             }
82             }
83              
84 0           return;
85             }
86              
87             # Process 'Tags'.
88             sub _process {
89 0     0     my ($self, $images_ar) = @_;
90              
91 0           $self->_check_images($images_ar);
92              
93             $self->{'tags'}->put(
94             ['b', 'div'],
95             ['a', 'class', $self->{'css_image_grid'}],
96              
97             ['b', 'div'],
98 0           ['a', 'class', $self->{'css_image_grid'}.'-inner'],
99             );
100 0 0         if (defined $self->{'title'}) {
101             $self->{'tags'}->put(
102             ['b', 'fieldset'],
103             ['b', 'legend'],
104 0           ['d', $self->{'title'}],
105             ['e', 'legend'],
106             );
107             }
108 0           foreach my $image (@{$images_ar}) {
  0            
109              
110             # Begin of image link.
111 0 0         if (defined $self->{'img_link_cb'}) {
112             $self->{'tags'}->put(
113             ['b', 'a'],
114 0           ['a', 'href', $self->{'img_link_cb'}->($image)],
115             );
116             }
117              
118             # Begin of figure.
119 0           $self->{'tags'}->put(
120             ['b', 'figure'],
121             );
122              
123             # Select information.
124 0 0         if (defined $self->{'img_select_cb'}) {
125 0           my $select_hr = $self->{'img_select_cb'}->($self, $image);
126 0 0 0       if (ref $select_hr eq 'HASH' && exists $select_hr->{'value'}) {
127 0   0       $select_hr->{'css_background_color'} ||= 'lightgreen';
128             $self->{'tags'}->put(
129             ['b', 'i'],
130             ['a', 'class', 'selected'],
131             ['a', 'style', 'background-color: '.$select_hr->{'css_background_color'}.';'],
132             exists $select_hr->{'value'} ? (
133 0 0         ['d', $select_hr->{'value'}],
134             ) : (),
135             ['e', 'i'],
136             );
137             }
138             }
139              
140             # Image.
141 0           my $image_url;
142 0 0         if (defined $image->url) {
    0          
    0          
143 0           $image_url = $image->url;
144             } elsif (defined $image->url_cb) {
145 0           $image_url = $image->url_cb->($image);
146             } elsif (defined $self->{'img_src_cb'}) {
147 0           $image_url = $self->{'img_src_cb'}->($image);
148             } else {
149 0           err 'No image URL.';
150             }
151 0           my $img_style;
152 0 0 0       if (defined $self->{'img_border_width'} && defined $self->{'img_border_color_cb'}) {
153 0           my $border_color = $self->{'img_border_color_cb'}->($self, $image);
154 0 0         if (defined $border_color) {
155 0           $img_style = 'border:'.$self->{'img_border_width'}.'px solid '.$border_color.';';
156             }
157             }
158 0 0         $self->{'tags'}->put(
159             ['b', 'img'],
160             defined $img_style ? (
161             ['a', 'style', $img_style],
162             ['a', 'class', 'border'],
163             ) : (),
164             ['a', 'src', $image_url],
165             ['e', 'img'],
166             );
167              
168             # Image comment.
169 0 0         if (defined $image->comment) {
170 0           $self->{'tags'}->put(
171             ['b', 'figcaption'],
172             ['d', $image->comment],
173             ['e', 'figcaption'],
174             );
175             }
176              
177             # Enf of figure.
178 0           $self->{'tags'}->put(
179             ['e', 'figure'],
180             );
181              
182             # End of image link.
183 0 0         if (defined $self->{'img_link_cb'}) {
184 0           $self->{'tags'}->put(
185             ['e', 'a'],
186             );
187             }
188             }
189 0 0         if (defined $self->{'title'}) {
190 0           $self->{'tags'}->put(
191             ['e', 'fieldset'],
192             );
193             }
194 0           $self->{'tags'}->put(
195             ['e', 'div'],
196             ['e', 'div'],
197             );
198              
199 0           return;
200             }
201              
202             sub _process_css {
203 0     0     my $self = shift;
204              
205             # Compute image width and height.
206 0           my ($img_width, $img_height) = ($self->{'img_width'}, $self->{'img_width'});
207 0 0         if (defined $self->{'img_border_width'}) {
208 0           $img_width -= 2 * $self->{'img_border_width'};
209 0           $img_height -= 2 * $self->{'img_border_width'};
210             }
211              
212             $self->{'css'}->put(
213              
214             # Grid center on page.
215             ['s', '.'.$self->{'css_image_grid'}],
216             ['d', 'display', 'flex'],
217             ['d', 'align-items', 'center'],
218             ['d', 'justify-content', 'center'],
219             ['e'],
220              
221             # 4 columns in grid.
222             ['s', '.'.$self->{'css_image_grid'}.'-inner'],
223             ['d', 'display', 'grid'],
224             ['d', 'grid-gap', '1px'],
225             ['d', 'grid-template-columns', 'repeat(4, '.$self->{'img_width'}.'px)'],
226             ['e'],
227              
228             # Create rectangle.
229             ['s', '.'.$self->{'css_image_grid'}.' figure'],
230             ['d', 'object-fit', 'cover'],
231             ['d', 'width', $self->{'img_width'}.'px'],
232             ['d', 'height', $self->{'img_width'}.'px'],
233             ['d', 'position', 'relative'],
234             ['d', 'overflow', 'hidden'],
235             ['d', 'margin', 0],
236             ['d', 'padding', 0],
237             ['e'],
238              
239             ['s', '.'.$self->{'css_image_grid'}.' img'],
240             ['d', 'object-fit', 'cover'],
241             ['d', 'width', '100%'],
242             ['d', 'height', '100%'],
243             ['d', 'vertical-align', 'middle'],
244             ['e'],
245              
246             ['s', '.'.$self->{'css_image_grid'}.' img.border'],
247             ['d', 'object-fit', 'cover'],
248             ['d', 'width', $img_width.'px'],
249             ['d', 'height', $img_height.'px'],
250             ['d', 'vertical-align', 'middle'],
251             ['e'],
252              
253             ['s', '.'.$self->{'css_image_grid'}.' figcaption'],
254             ['d', 'margin', 0],
255             ['d', 'padding', '1em'],
256             ['d', 'position', 'absolute'],
257             ['d', 'z-index', 1],
258             ['d', 'bottom', 0],
259             ['d', 'left', 0],
260             ['d', 'width', '100%'],
261             ['d', 'max-height', '100%'],
262             ['d', 'overflow', 'auto'],
263             ['d', 'box-sizing', 'border-box'],
264             ['d', 'transition', 'transform 0.5s'],
265             ['d', 'transform', 'translateY(100%)'],
266             ['d', 'background', 'rgba(0, 0, 0, 0.7)'],
267             ['d', 'color', 'rgb(255, 255, 255)'],
268             ['e'],
269              
270             ['s', '.'.$self->{'css_image_grid'}.' figure:hover figcaption'],
271             ['d', 'transform', 'translateY(0%)'],
272             ['e'],
273              
274 0           ['s', '.'.$self->{'css_image_grid'}.' .selected'],
275             ['d', 'border', '1px solid black'],
276             ['d', 'border-radius', '0.5em'],
277             ['d', 'color', 'black'],
278             ['d', 'padding', '0.5em'],
279             ['d', 'position', 'absolute'],
280             ['d', 'right', '10px'],
281             ['d', 'top', '10px'],
282             ['e'],
283             );
284              
285 0           return;
286             }
287              
288             1;
289              
290             __END__