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__ |