File Coverage
blib/lib/CGI/List.pm
Criterion
Covered
Total
%
statement
21
594
3.5
branch
0
264
0.0
condition
0
67
0.0
subroutine
7
41
17.0
pod
10
34
29.4
total
38
1000
3.8
line
stmt
bran
cond
sub
pod
time
code
1
package CGI::List;
2
3
1
1
25913
use strict;
1
2
1
37
4
1
1
5
use Carp qw(croak carp);
1
1
1
62
5
6
require 5.004;
7
1
1
2141
use CGI qw/:standard *table/;
1
17551
1
7
8
1
1
4446
use Math::Round(qw/nearest nhimult/);
1
12870
1
7177
9
10
=head1 NAME
11
12
CGI::List - Easily generate HTML Lists From a DataBase
13
14
=head1 VERSION
15
16
Version 0.05
17
18
=cut
19
20
our $VERSION = '0.05';
21
22
sub new {
23
0
0
1
my $class = shift;
24
0
my (%params) = @_;
25
0
my $self = {};
26
0
bless $self,$class;
27
28
#Init params
29
0
0
defined param("cg_list") or param(-name=>"cg_list", -value=>"");
30
0
0
defined param("cg_order") or param(-name=>"cg_order",-value=>"");
31
0
0
defined param("cg_side") or param(-name=>"cg_side", -value=>"");
32
0
0
defined param("cg_page") or param(-name=>"cg_page", -value=>"1");
33
34
#Prevent attacks
35
0
0
param(-name=>"cg_order",-value=>int(param("cg_order") || 0));
36
0
0
param(-name=>"cg_page",-value=>int(param("cg_page") || 0));
37
38
#Predefined values
39
0
$self->{name} = "cg_list";
40
0
$self->{debug} = 0;
41
0
$self->{on_errors} = "print";
42
0
$self->{auto_order} = 1;
43
0
$self->{pagination} = 1;
44
0
$self->{nav_pages} = 4;
45
0
($self->{script},$self->{p}) = split(/\?/,$ENV{REQUEST_URI});
46
47
0
$self->{table} = {
48
width => "100%",
49
class => "cg_table",
50
align => "center",
51
cellpadding => "0",
52
cellspacing => "0",
53
};
54
55
0
$self->{columns}= {params => {}};
56
0
$self->{th} = {params => {align => "center"}};
57
0
$self->{detail_th} = {params => {}};
58
0
$self->{group_th} = {params => {align=>"left",class=>"cg_group_th"}};
59
0
$self->{group_td} = {params => {align=>"left",class=>"cg_group_td"}};
60
61
0
$self->{group_item_totals} = {td=>{params=>{class=>"cg_group_item_totals"}}};
62
63
64
0
$self->{detail}{td}{params} = {};
65
0
$self->{detail}{Tr}{params_a} = {class=> "cg_row_a"};
66
0
$self->{detail}{Tr}{params_b} = {class=> "cg_row_b"};
67
68
0
$self->{no_data}{params} = {class=>"cg_no_data", align=>"center"};
69
70
0
$self->{totals}{td}{params} = {align=>"right",class=>"cg_cell_total"};
71
0
$self->{totals}{Tr}{params} = {class=>"cg_row_total"};
72
73
0
$self->{foother}{params} = {class=>"cg_foother"};
74
75
0
$self->{nw_params}="width=600,height=500,toolbar=no,scrollbars=yes,top='+((screen.height/2)-250)+',left='+((screen.width/2)-300)+'";
76
77
0
$self->{orders} = {};
78
79
0
$self->{labels} = {
80
page_of => 'Page _PAGE_ of _OF_',
81
no_data => 'No records found',
82
link_up => '↑',
83
link_down => '↓',
84
next_page => '»',
85
previous_page => '«',
86
number_of_rows => "_NUMBER_ rows",
87
};
88
89
0
$self->{Number_Format}={THOUSANDS_SEP=>",",DECIMAL_POINT=>".",MON_THOUSANDS_SEP=>",","MON_DECIMAL_POINT"=>".","INT_CURR_SYMBOL"=>'$'};
90
91
#Put all Parameters on the object
92
0
foreach my $init_param(keys %params){
93
0
$self->{$init_param} = $params{$init_param};
94
}
95
96
97
#Order params and Query
98
0
0
0
if ($self->{auto_order} and param('cg_order') and param('cg_list') eq $self->{name}){
0
99
0
0
if(param("cg_order") =~ /\w+/){
100
0
$self->{sql}{order_by} = param("cg_order");
101
0
0
$self->{sql}{order_by} .= " DESC " if (param("cg_side"));
102
0
0
$self->{sql}{order_by} .= " ASC " if (!param("cg_side"));
103
}
104
}
105
106
0
$self->{transit_params} = "";
107
0
$self->{cgi_cg_params} = "";
108
109
0
0
0
$self->{link}{event} = "onClick" if($self->{link} and !$self->{link}{event});
110
111
0
return $self;
112
}
113
114
sub print {
115
0
0
1
my $self = shift;
116
0
my $grid = "";
117
118
0
$self->transit_params();
119
0
0
if(!defined $self->{rs}){
120
0
$grid .= $self->get_data();
121
}
122
123
0
$self->{table}{id} = 'cg_table_' . $self->{name};
124
# $grid .= ' ';
125
0
$grid .= "\n";
126
0
$grid .= start_table($self->{table}) . "\n";
127
0
0
$grid .= "$self->{caption} " if($self->{caption});
128
0
0
if(defined $self->{groups}){
129
0
$grid .= $self->print_group_columns();
130
0
$grid .= $self->print_group_detail();
131
0
0
if(!$self->{rows}){
132
0
$self->{no_data}{params}{colspan} = $self->{colspan};
133
0
$grid .= " " . Tr ({},td($self->{no_data}{params},$self->{labels}{no_data})) . "\n";
134
}else{
135
0
$grid .= $self->print_group_totals;
136
0
$grid .= $self->print_pagination();
137
}
138
}else{
139
0
$grid .= $self->print_columns();
140
0
$grid .= $self->print_detail();
141
0
0
if(!$self->{rows}){
142
0
$self->{no_data}{params}{colspan} = $self->{colspan};
143
0
$grid .= " " . Tr ({},td($self->{no_data}{params},$self->{labels}{no_data})) . "\n";
144
}else{
145
0
$grid .= $self->print_totals;
146
0
$grid .= $self->print_pagination();
147
}
148
}
149
0
$grid .= "
\n";
150
0
$grid .= $self->js_row_effect();
151
152
0
return $grid;
153
}
154
155
sub get_data {
156
0
0
0
my $self = shift;
157
158
0
$self->build_query();
159
160
0
$self->{sth} = $self->{dbh}->prepare($self->{sql}{query});
161
0
eval {
162
0
0
if($self->{sql}{params}){
163
0
$self->{sth}->execute(@{$self->{sql}{params}});
0
164
}else{
165
0
$self->{sth}->execute();
166
}
167
};
168
#if sql errors
169
0
0
if($@){
170
0
0
if($self->{on_errors} eq "die"){
0
0
171
0
0
if($self->{debug}){
172
0
croak "CGI::List Error code: ".$self->{dbh}->err.". Error message: ".$self->{dbh}->errstr . " SQL: " . $self->{sql}{query};
173
}else{
174
0
croak "CGI::List Error code: " . $self->{dbh}->err . ". Error message: " . $self->{dbh}->errstr;
175
}
176
0
return "";
177
}elsif($self->{on_errors} eq "warn"){
178
0
0
if($self->{debug}){
179
0
carp "CGI::List Error code: ".$self->{dbh}->err.". Error message: ".$self->{dbh}->errstr . " SQL: " . $self->{sql}{query};
180
}else{
181
0
carp "CGI::List Error code: " . $self->{dbh}->err . ". Error message: " . $self->{dbh}->errstr;
182
}
183
0
return "";
184
}elsif($self->{on_errors} eq "print"){
185
0
0
if($self->{debug}){
186
0
return "CGI::List Error code: " . $self->{dbh}->err .". Error message: ".$self->{dbh}->errstr." SQL: ".$self->{sql}{query};
187
}else{
188
0
return "CGI::List Error code: " . $self->{dbh}->err .". Error message: ".$self->{dbh}->errstr;
189
}
190
}
191
# }
192
#
193
# if ( defined $self->{dbh}->errstr ) {
194
#
195
}else{
196
0
while ( my $rec = $self->{sth}->fetchrow_hashref() ) {
197
0
push (@{$self->{rs}},$rec);
0
198
}
199
}
200
0
return "";
201
}
202
203
sub build_query {
204
0
0
0
my $self = shift;
205
0
0
if (ref \$self->{sql} eq "SCALAR"){
206
0
my $query = $self->{sql};
207
0
$self->{sql} = {
208
query => $query,
209
};
210
0
$self->{auto_order} = 0;
211
0
$self->{pagination} = 0;
212
}else{
213
0
0
defined $self->{sql}{select} or $self->{sql}{select} = "";
214
0
0
defined $self->{sql}{from} or $self->{sql}{from} = "";
215
0
0
defined $self->{sql}{where} or $self->{sql}{where} = "";
216
0
0
defined $self->{sql}{order_by} or $self->{sql}{order_by} = "";
217
0
0
defined $self->{sql}{limit} or $self->{sql}{limit} = "";
218
0
0
defined $self->{sql}{offset} or $self->{sql}{offset} = "";
219
0
$self->{sql}{query} = " SELECT " . $self->{sql}{select};
220
0
0
$self->{sql}{query} .= " FROM " . $self->{sql}{from} if $self->{sql}{from};
221
0
0
$self->{sql}{query} .= " WHERE " . $self->{sql}{where} if $self->{sql}{where};
222
0
0
$self->{sql}{query} .= " GROUP BY " . $self->{sql}{group_by} if $self->{sql}{group_by};
223
0
0
$self->{sql}{query} .= " ORDER BY " . $self->{sql}{order_by} if $self->{sql}{order_by};
224
0
0
$self->{sql}{query} .= " LIMIT " . $self->{sql}{limit} if $self->{sql}{limit};
225
0
0
if($self->{pagination}){
226
0
$self->{sql}{query} .= " OFFSET " . ($self->{sql}{limit} * (param("cg_page") - 1) );
227
}else{
228
0
0
$self->{sql}{query} .= " OFFSET " . $self->{sql}{offset} if $self->{sql}{offset};
229
}
230
}
231
}
232
233
sub print_columns {
234
0
0
0
my $self = shift;
235
0
$self->get_columns();
236
0
0
if(defined $self->{headers_groups}){
237
0
my $HTML = "";
238
0
$self->{th}{params}{align} = "center";
239
0
foreach my $hgroup (@{$self->{headers_groups}}){
0
240
0
0
if(ref $hgroup eq "HASH" ){
241
0
$self->{th}{params}{colspan} = $hgroup->{colspan};
242
0
$HTML .= th($self->{th}{params},$hgroup->{label}) . "\n";
243
0
undef $self->{th}{params}{colspan};
244
}else{
245
0
$HTML .= th($self->{th}{params},"") . "\n";
246
}
247
}
248
0
my $line1 = Tr ($self->{columns}{params},$HTML);
249
0
$HTML = "";
250
0
undef $self->{th}{params}{align};
251
0
my $it = 0;
252
0
foreach my $label (@{$self->{columns}{labels}}){
0
253
0
0
$self->{th}{params}{width} = $self->{columns_width}[$it] if(defined $self->{columns_width}[$it]);
254
0
0
$self->{th}{params}{align} = $self->{columns_headers_align}[$it] if(defined $self->{columns_headers_align}[$it]);
255
0
$HTML .= th($self->{th}{params},$label) . "\n";
256
0
$it++;
257
}
258
0
return $line1 . "\n " . Tr ($self->{columns}{params},$HTML);
259
}else{
260
0
0
0
if (defined $self->{columns_width} or defined $self->{columns_headers_align}){
261
0
my $HTML = "";
262
0
my $it = 0;
263
0
foreach my $label (@{$self->{columns}{labels}}){
0
264
0
0
$self->{th}{params}{width} = $self->{columns_width}[$it] if(defined $self->{columns_width}[$it]);
265
0
0
$self->{th}{params}{align} = $self->{columns_headers_align}[$it] if(defined $self->{columns_headers_align}[$it]);
266
0
$HTML .= th($self->{th}{params},$label) . "\n";
267
0
$it++;
268
}
269
0
return " " . Tr ($self->{columns}{params},$HTML);
270
};
271
0
return " " . Tr ($self->{columns}{params},[th($self->{th}{params},$self->{columns}{labels})]) . "\n";
272
}
273
}
274
275
sub get_columns {
276
0
0
0
my $self = shift;
277
0
$self->{columns}{names} = ();
278
0
$self->{columns}{labels} = ();
279
0
0
$self->{colspan} = ($self->{sth}->{NUM_OF_FIELDS}) || 0;
280
0
foreach my $i(0 .. ($self->{colspan} - 1)) {
281
0
0
defined $self->{sth}->{NAME}->[$i] or $self->{sth}->{NAME}->[$i] = "";
282
0
0
0
if ($self->{sth}->{NAME}->[$i] and !($self->{link}{hidde_key_col} and $self->{sth}->{NAME}->[$i] eq $self->{link}{key})){
0
283
284
0
push(@{$self->{columns}{names}},$self->{sth}->{NAME}->[$i]);
0
285
0
my $col_label = $self->{sth}->{NAME}->[$i];
286
0
$col_label =~ s/_/ /g;
287
0
$col_label = ucfirst($col_label);
288
289
#Auto order Links
290
0
my $side = 0;
291
0
0
$side = 1 if (!param("cg_side"));
292
0
0
if($self->{auto_order}){
293
0
0
if(($i+1) eq param("cg_order")){
294
0
0
if(param("cg_side") eq "0"){
0
295
0
$col_label .= ' ' . a({href=>$self->{script} . "?cg_order=".($i+1)."&cg_side=1&cg_page=" . param("cg_page") . "&cg_list=" . $self->{name} . $self->{transit_params}},$self->{labels}{link_up});
296
0
$col_label .= $self->{labels}{link_down};
297
}elsif(param("cg_side") eq "1"){
298
0
$col_label .= ' ' . $self->{labels}{link_up};
299
0
$col_label .= a({href=>$self->{script} . "?cg_order=".($i+1)."&cg_side=0&cg_page=" . param("cg_page") . "&cg_list=" . $self->{name} . $self->{transit_params}},$self->{labels}{link_down});
300
}
301
}else{
302
0
$col_label .= ' ' .a({href=>$self->{script} . "?cg_order=".($i+1)."&cg_side=1&cg_page=" . param("cg_page") . "&cg_list=" . $self->{name} . $self->{transit_params}},$self->{labels}{link_up});
303
0
$col_label .= a({href=>$self->{script} . "?cg_order=".($i+1)."&cg_side=0&cg_page=" . param("cg_page") . "&cg_list=" . $self->{name} . $self->{transit_params}},$self->{labels}{link_down});
304
}
305
}
306
0
push(@{$self->{columns}{labels}},$col_label);
0
307
}
308
}
309
0
0
$self->{colspan} -= 1 if($self->{link}{hidde_key_col});
310
}
311
312
sub print_detail {
313
0
0
0
my $self = shift;
314
0
my $HTML = "";
315
316
0
$self->{rows} = 0;
317
0
foreach my $rec(@{$self->{rs}}) {
0
318
0
$self->{rows} ++;
319
0
my @fields;
320
0
my $row_cells = "";
321
0
my $row_params = "params_b";
322
0
my $row_html_params = 0;
323
0
0
$row_params = "params_a" if (($self->{rows}/2) - int($self->{rows}/2));
324
0
foreach my $i(0 .. (($self->{colspan}-1))) {
325
0
0
if(defined $self->{columns_align}){
326
0
$self->{detail}{td}{params}{align} = $self->{columns_align}[$i];
327
}
328
329
0
0
if(defined $self->{cell_format}{$self->{columns}{names}[$i]}){
330
#Cell Formats
331
0
my $cell_params = $self->{detail}{td}{params};
332
0
foreach my $cell_format(@{$self->{cell_format}{$self->{columns}{names}[$i]}}){
0
333
0
my $check = 0;
334
0
my $condition = $cell_format->{condition};
335
0
$condition =~ s/%%/$rec->{$self->{columns}{names}[$i]}/g;
336
0
$condition =~/([\S\s]+)\s(\S+)\s([\S\s]+)/;
337
0
0
my $untained_condition = " $1 $2 $3" || "";
338
0
eval '$check = 1 if(' . $untained_condition . ');';
339
0
0
if( $check ){
340
0
$cell_params = $cell_format->{params};
341
}
342
}
343
0
$row_cells .= td($cell_params,$rec->{$self->{columns}{names}[$i]});
344
}else{
345
#Normal cell
346
0
$row_cells .= td($self->{detail}{td}{params},$rec->{$self->{columns}{names}[$i]});
347
}
348
0
0
if(defined $self->{row_format}{$self->{columns}{names}[$i]}){
349
#Row Format
350
0
foreach my $row_format(@{$self->{row_format}{$self->{columns}{names}[$i]}}){
0
351
0
my $check = 0;
352
0
my $condition = $row_format->{condition};
353
0
$condition =~ s/%%/$rec->{$self->{columns}{names}[$i]}/g;
354
0
$condition =~/([\S\s]+)\s(\S+)\s([\S\s]+)/;
355
0
0
my $untained_condition = " $1 $2 $3" || "";
356
0
eval '$check = 1 if(' . $untained_condition . ');';
357
0
0
if( $check ){
358
0
$row_params = $self->{columns}{names}[$i];
359
0
$self->{detail}{Tr}{$row_params} = $row_format->{params};
360
0
$row_html_params = 1;
361
}
362
}
363
}
364
}
365
366
367
368
369
370
371
372
#Links
373
0
0
if($self->{link}){
374
0
0
if($self->{link}{target}){
0
0
375
0
$self->{detail}{Tr}{$row_params}{$self->{link}{event}} = "window.open('" . $self->{link}{location} . "?" . $self->{link}{key} . "=" . $rec->{$self->{link}{key}} . "$self->{transit_params}','" . $self->{key}{target} . "','" . $self->{nw_params} . "');";
376
}elsif($self->{opener}){
377
0
my $opener_transit_params = $self->{transit_params};
378
0
$opener_transit_params =~ s/opener=[\w]*//g;
379
0
$self->{detail}{Tr}{$row_params}{$self->{link}{event}} = "opener.location.href='" . $self->{opener} . "?" . $self->{link}{key} . "=" . $rec->{$self->{link}{key}} . "$opener_transit_params'; window.close();";
380
}elsif($self->{link}{location}){
381
0
$self->{detail}{Tr}{$row_params}{$self->{link}{event}} = "document.location.href='" . $self->{link}{location} . "?" . $self->{link}{key} . "=" . $rec->{$self->{link}{key}} . "$self->{transit_params}';";
382
}
383
}
384
0
$HTML .= " " . Tr ($self->{detail}{Tr}{$row_params},$row_cells) . "\n";
385
}
386
387
0
return $HTML;
388
}
389
390
sub js_row_effect {
391
0
0
0
my $self = shift;
392
0
my $HTML = "";
393
#Row Efect
394
0
0
0
if($self->{opener} or $self->{link}{location}){
395
0
$HTML .= '
405
'
406
}
407
0
return $HTML;
408
}
409
410
sub transit_params {
411
0
0
0
my $self = shift;
412
#Transit Params
413
0
$self->{cgi_cg_params} = "cg_order=" . param("cg_order") .
414
"&cg_side=" . param("cg_side") .
415
"&cg_page=" . param("cg_page") .
416
"&cg_list=" . $self->{name};
417
0
0
if (defined $self->{link}{transit_params}){
418
0
foreach my $k (sort keys %{$self->{link}{transit_params}}){
0
419
0
$self->{transit_params} .= "&" . $k . "=" . $self->{link}{transit_params}{$k};
420
}
421
}
422
0
0
if($self->{opener}){
423
0
$self->{transit_params} .= "&opener=" . $self->{opener};
424
}
425
}
426
427
sub print_pagination {
428
0
0
0
my $self = shift;
429
0
my $HTML = "";
430
0
$self->{foother}{params}{colspan} = $self->{colspan}+1;
431
0
0
if($self->{pagination}){
432
#Get total rows
433
0
my $sSQL = "SELECT count(*) AS total FROM " . $self->{sql}{from};
434
0
0
$sSQL .= " WHERE " . $self->{sql}{where} if $self->{sql}{where};
435
0
my $total = $self->{dbh}->selectrow_hashref($sSQL,{},@{$self->{sql}{params}});
0
436
0
my $pages = ($total->{total} / $self->{sql}{limit});
437
0
my $pages_int = int($pages);
438
0
0
$pages = $pages_int + 1 if($pages > $pages_int);
439
440
0
my $pagination = $self->{labels}{page_of};
441
0
0
my $page = param("cg_page") || 1;
442
0
$pagination =~ s/_PAGE_/$page/;
443
0
$pagination =~ s/_OF_/$pages/;
444
0
$pagination .= " ";
445
0
0
if(param("cg_page") > 1){
446
0
$pagination .= " " .a({-href => $self->{script} . "?cg_page=" . (param("cg_page")-1) . "&cg_order=" . param("cg_order") . "&cg_side=" . param("cg_side") . "&cg_list=" . $self->{name} . $self->{transit_params}},
447
$self->{labels}{previous_page}) . " ";
448
0
foreach(my $ii = $self->{nav_pages} -1;$ii > 0;$ii--){
449
0
0
$pagination .= " " .a({-href => $self->{script} . "?cg_page=" . (param("cg_page") - $ii) . "&cg_order=" . param("cg_order") . "&cg_side=" . param("cg_side") . "&cg_list=" . $self->{name} . $self->{transit_params}},
450
(param("cg_page") - $ii)) if((param("cg_page") - $ii) > 0);
451
}
452
}
453
0
0
$pagination .= " | " if($pages > 1);
454
0
0
if(param("cg_page") < $pages){
455
0
foreach(my $ii = 1;$ii < $self->{nav_pages};$ii++){
456
0
0
$pagination .= " " .a({-href => $self->{script} . "?cg_page=" . (param("cg_page") + $ii) . "&cg_order=" . param("cg_order") . "&cg_side=" . param("cg_side") . "&cg_list=" . $self->{name} . $self->{transit_params}},
457
(param("cg_page") + $ii)) if((param("cg_page") + $ii) <= $pages);
458
}
459
0
$pagination .= " " .a({-href => $self->{script} . "?cg_page=" . (param("cg_page") +1) . "&cg_order=" . param("cg_order") . "&cg_side=" . param("cg_side") . "&cg_list=" . $self->{name} . $self->{transit_params},-alt=>"Siguiente"},$self->{labels}{next_page});
460
}
461
462
463
0
my $rows = $self->{labels}{number_of_rows};
464
0
$rows =~ s/_NUMBER_/$self->{rows}/g;
465
466
0
$HTML .= " " . Tr ({},td($self->{foother}{params},
467
'' . $rows . ' ' .
468
'' . $pagination . ' '
469
)) . "\n";
470
}else{
471
0
my $rows = $self->{labels}{number_of_rows};
472
0
$rows =~ s/_NUMBER_/$self->{rows}/g;
473
474
0
$HTML .= " " . Tr ({},td($self->{foother}{params},
475
'' . $rows . ' '
476
)) . "\n";
477
}
478
0
return $HTML;
479
}
480
481
sub row_format {
482
0
0
1
my $self = shift;
483
0
my %params = @_;
484
0
push(@{$self->{row_format}{$params{name}}},{'params' => $params{params},condition => $params{condition}});
0
485
}
486
487
sub cell_format {
488
0
0
1
my $self = shift;
489
0
my %params = @_;
490
0
push(@{$self->{cell_format}{$params{name}}},{'params' => $params{params},condition => $params{condition}});
0
491
}
492
493
sub group {
494
0
0
1
my $self = shift;
495
0
my %params = @_;
496
0
push(@{$self->{groups}},{'key' => $params{key},fields => $params{fields}});
0
497
0
foreach my $field(@{$params{fields}}){
0
498
0
push(@{$self->{group_fields_array}},$field);
0
499
0
$self->{group_fields_hash}{$field} = 1;
500
}
501
502
0
0
if($self->{sql}{order_by}){
503
0
0
$self->{sql}{order_by} = ($params{order_by} || $params{key}) . ", $self->{sql}{order_by}";
504
}else{
505
0
0
$self->{sql}{order_by} = "$params{order_by}" || $params{key};
506
}
507
}
508
509
sub columns_width {
510
0
0
1
my $self = shift;
511
0
$self->{columns_width} = shift;
512
}
513
514
sub columns_align {
515
0
0
1
my $self = shift;
516
0
$self->{columns_align} = shift;
517
}
518
519
sub columns_headers_align {
520
0
0
1
my $self = shift;
521
0
$self->{columns_headers_align} = shift;
522
}
523
524
sub print_group_columns {
525
0
0
0
my $self = shift;
526
0
my @labels;
527
0
foreach my $field(@{$self->{group_fields_array}}){
0
528
0
push(@labels,ucfirst($field));
529
}
530
0
return " " . Tr ($self->{columns}{params},[th($self->{group_th}{params},\@labels)]) . "\n";
531
}
532
533
sub print_group_item {
534
0
0
0
my $self = shift;
535
0
my $rec = shift;
536
0
my @data;
537
0
foreach my $key (@{$self->{group_fields_array}}){
0
538
0
push(@data,$rec->{$key});
539
}
540
0
return " " . Tr ($self->{columns}{params},[td($self->{group_td}{params},\@data)]) . "\n";
541
}
542
543
sub print_group_detail {
544
0
0
0
my $self = shift;
545
0
my $HTML = "";
546
547
0
$self->{rows} = 0;
548
0
my $group = undef;
549
0
$self->get_detail_columns();
550
0
foreach my $rec(@{$self->{rs}}) {
0
551
#Group items
552
0
0
if($group ne $rec->{$self->{groups}[0]{key}}){
553
0
0
if($group ne undef){
554
0
$HTML .= $self->print_group_item_totals($self->{groups}[0]{key},$group);
555
0
$HTML .= "\n";
556
0
$HTML .= " \n \n";
557
}
558
0
$group = $rec->{$self->{groups}[0]{key}};
559
0
$HTML .= $self->print_group_item($rec);
560
0
$HTML .= " \n \n";
0
561
0
$self->{table}{class} = "cg_detail_table";
562
0
$HTML .= start_table($self->{table}) . "\n";
563
0
$HTML .= $self->print_detail_columns();
564
}
565
566
0
$self->{rows} ++;
567
0
my @fields;
568
0
my $row_cells = "";
569
0
my $row_params = "params_b";
570
0
my $row_html_params = 0;
571
0
0
$row_params = "params_a" if (($self->{rows}/2) - int($self->{rows}/2));
572
0
foreach my $i(0 .. (($self->{colspan})- scalar(@{$self->{group_fields_array}}))) {
0
573
0
0
if(defined $self->{columns_align}){
574
0
$self->{detail}{td}{params}{align} = $self->{columns_align}[$i];
575
}
576
0
0
if(defined $self->{cell_format}{$self->{columns}{names}[$i]}){
577
#Cell Formats
578
0
my $cell_params = $self->{detail}{td}{params};
579
0
foreach my $cell_format(@{$self->{cell_format}{$self->{columns}{names}[$i]}}){
0
580
0
my $check = 0;
581
0
my $condition = $cell_format->{condition};
582
0
$condition =~ s/%%/$rec->{$self->{columns}{names}[$i]}/g;
583
0
$condition =~/([\S\s]+)\s(\S+)\s([\S\s]+)/;
584
0
0
my $untained_condition = " $1 $2 $3" || "";
585
0
eval '$check = 1 if(' . $untained_condition . ');';
586
0
0
if( $check ){
587
0
$cell_params = $cell_format->{params};
588
}
589
}
590
0
$row_cells .= td($cell_params,$rec->{$self->{columns}{names}[$i]});
591
}else{
592
#Normal cell
593
0
$row_cells .= td($self->{detail}{td}{params},$rec->{$self->{columns}{names}[$i]});
594
}
595
0
0
if(defined $self->{row_format}{$self->{columns}{names}[$i]}){
596
# #Row Format
597
0
foreach my $row_format(@{$self->{row_format}{$self->{columns}{names}[$i]}}){
0
598
0
my $check = 0;
599
0
my $condition = $row_format->{condition};
600
0
$condition =~ s/%%/$rec->{$self->{columns}{names}[$i]}/g;
601
0
$condition =~/([\S\s]+)\s(\S+)\s([\S\s]+)/;
602
0
0
my $untained_condition = " $1 $2 $3" || "";
603
0
eval '$check = 1 if(' . $untained_condition . ');';
604
0
0
if( $check ){
605
0
$row_params = $self->{columns}{names}[$i];
606
0
$self->{detail}{Tr}{$row_params} = $row_format->{params};
607
0
$row_html_params = 1;
608
}
609
}
610
}
611
}
612
613
614
# #Links
615
0
0
if($self->{link}){
616
0
0
if($self->{link}{target}){
0
0
617
0
$self->{detail}{Tr}{$row_params}{$self->{link}{event}} = "window.open('" . $self->{link}{location} . "?" . $self->{link}{key} . "=" . $rec->{$self->{link}{key}} . "$self->{transit_params}','" . $self->{key}{target} . "','" . $self->{nw_params} . "');";
618
}elsif($self->{opener}){
619
0
my $opener_transit_params = $self->{transit_params};
620
0
$opener_transit_params =~ s/opener=[\w]*//g;
621
0
$self->{detail}{Tr}{$row_params}{$self->{link}{event}} = "opener.location.href='" . $self->{opener} . "?" . $self->{link}{key} . "=" . $rec->{$self->{link}{key}} . "$opener_transit_params'; window.close();";
622
}elsif($self->{link}{location}){
623
0
$self->{detail}{Tr}{$row_params}{$self->{link}{event}} = "document.location.href='" . $self->{link}{location} . "?" . $self->{link}{key} . "=" . $rec->{$self->{link}{key}} . "$self->{transit_params}';";
624
}
625
}
626
0
$HTML .= " " . Tr ($self->{detail}{Tr}{$row_params},$row_cells) . "\n";
627
}
628
0
0
if($HTML){
629
0
$HTML .= $self->print_group_item_totals($self->{groups}[0]{key},$group);
630
0
$HTML .= "\n";
631
0
$HTML .= " \n \n";
632
}
633
0
return $HTML;
634
}
635
636
sub print_detail_columns {
637
0
0
0
my $self = shift;
638
0
0
0
if (defined $self->{columns_width} or defined $self->{columns_headers_align}){
639
0
my $HTML = "";
640
0
my $it = 0;
641
0
foreach my $label (@{$self->{columns}{labels}}){
0
642
0
0
$self->{detail_th}{params}{width} = $self->{columns_width}[$it] if(defined $self->{columns_width}[$it]);
643
0
0
$self->{detail_th}{params}{align} = $self->{columns_headers_align}[$it] if(defined $self->{columns_headers_align}[$it]);
644
0
$HTML .= th($self->{detail_th}{params},$label) . "\n";
645
0
$it++;
646
}
647
0
return " " . Tr ($self->{columns}{params},$HTML);
648
};
649
0
return " " . Tr ($self->{columns}{params},[th($self->{detail_th}{params},$self->{columns}{labels})]) . "\n";
650
}
651
652
sub get_detail_columns {
653
0
0
0
my $self = shift;
654
0
$self->{columns}{names} = ();
655
0
$self->{columns}{labels} = ();
656
0
$self->{colspan} = ($self->{sth}->{NUM_OF_FIELDS});
657
0
foreach my $i(0 .. ($self->{colspan} - 1)) {
658
0
0
defined $self->{sth}->{NAME}->[$i] or $self->{sth}->{NAME}->[$i] = "";
659
0
0
0
if ($self->{sth}->{NAME}->[$i] and !($self->{link}{hidde_key_col} and $self->{sth}->{NAME}->[$i] eq $self->{link}{key}) and !$self->{group_fields_hash}{$self->{sth}->{NAME}->[$i]}){
0
0
660
661
0
push(@{$self->{columns}{names}},$self->{sth}->{NAME}->[$i]);
0
662
0
my $col_label = $self->{sth}->{NAME}->[$i];
663
0
$col_label =~ s/_/ /g;
664
0
$col_label = ucfirst($col_label);
665
666
#Auto order Links
667
0
my $side = 0;
668
0
0
$side = 1 if (!param("cg_side"));
669
0
0
if($self->{auto_order}){
670
0
0
if(($i+1) eq param("cg_order")){
671
0
0
if(param("cg_side") eq "0"){
0
672
0
$col_label .= ' ' . a({href=>$self->{script} . "?cg_order=".($i+1)."&cg_side=1&cg_page=" . param("cg_page") . "&cg_list=" . $self->{name} . $self->{transit_params}},$self->{labels}{link_up});
673
0
$col_label .= $self->{labels}{link_down};
674
}elsif(param("cg_side") eq "1"){
675
0
$col_label .= ' ' . $self->{labels}{link_up};
676
0
$col_label .= a({href=>$self->{script} . "?cg_order=".($i+1)."&cg_side=0&cg_page=" . param("cg_page") . "&cg_list=" . $self->{name} . $self->{transit_params}},$self->{labels}{link_down});
677
}
678
}else{
679
0
$col_label .= ' ' .a({href=>$self->{script} . "?cg_order=".($i+1)."&cg_side=1&cg_page=" . param("cg_page") . "&cg_list=" . $self->{name} . $self->{transit_params}},$self->{labels}{link_up});
680
0
$col_label .= a({href=>$self->{script} . "?cg_order=".($i+1)."&cg_side=0&cg_page=" . param("cg_page") . "&cg_list=" . $self->{name} . $self->{transit_params}},$self->{labels}{link_down});
681
}
682
}
683
0
push(@{$self->{columns}{labels}},$col_label);
0
684
}
685
}
686
0
0
$self->{colspan} -= 1 if($self->{link}{hidde_key_col});
687
}
688
689
sub total {
690
0
0
1
my $self = shift;
691
0
my %params = @_;
692
0
$self->{totals}{$params{key}} = {type => $params{type},operation=>$params{operation},label=>$params{label},format=>$params{format}};
693
}
694
695
sub group_total {
696
0
0
1
my $self = shift;
697
0
my %params = @_;
698
0
$self->{group_totals}{$params{key}} = {type => $params{type},operation=>$params{operation},label=>$params{label},format=>$params{format}};
699
}
700
701
sub print_totals {
702
0
0
0
my $self = shift;
703
0
my $HTML = "";
704
0
my @totals;
705
706
0
foreach my $i(0 .. (($self->{colspan} - 1))) {
707
0
0
if(!(defined $self->{totals}{$self->{columns}{names}[$i]})){
708
0
push(@totals,"");
709
0
next;
710
}
711
#Operaciones
712
0
my $total = "";
713
0
0
if(defined $self->{totals}{$self->{columns}{names}[$i]}{operation}){
714
0
0
if($self->{totals}{$self->{columns}{names}[$i]}{operation} eq "SUM"){
0
0
715
0
$total = $self->SUM($self->{columns}{names}[$i]);
716
}elsif($self->{totals}{$self->{columns}{names}[$i]}{operation} eq "AVG"){
717
0
$total = $self->AVG($self->{columns}{names}[$i]);
718
}elsif($self->{totals}{$self->{columns}{names}[$i]}{operation} eq "COUNT"){
719
0
$total = $self->COUNT($self->{columns}{names}[$i]);
720
}
721
}
722
723
#Formatos
724
0
0
if($self->{totals}{$self->{columns}{names}[$i]}{format} eq "price"){
725
1
1
1163
use Number::Format;
1
7456
1
434
726
0
my $NF = Number::Format->new(%{$self->{Number_Format}});
0
727
0
$total = $NF->format_price($total);
728
}
729
730
0
0
if($self->{totals}{$self->{columns}{names}[$i]}{label}){
731
0
my $total_label = $total;
732
0
$total = $self->{totals}{$self->{columns}{names}[$i]}{label};
733
0
$total =~ s/%%/$total_label/g;
734
}
735
0
push(@totals,$total);
736
}
737
738
0
return " " . Tr ($self->{totals}{Tr}{params},[td($self->{totals}{td}{params},\@totals)]) . "\n";
739
}
740
741
sub print_group_totals {
742
0
0
0
my $self = shift;
743
0
my $HTML = "";
744
0
my @totals;
745
746
0
foreach my $i(0 .. (($self->{colspan} - 1))) {
747
0
0
if(!(defined $self->{totals}{$self->{columns}{names}[$i]})){
748
0
next;
749
}
750
#Operaciones
751
0
my $total = "";
752
0
0
if(defined $self->{totals}{$self->{columns}{names}[$i]}{operation}){
753
0
0
if($self->{totals}{$self->{columns}{names}[$i]}{operation} eq "SUM"){
0
0
754
0
$total = $self->SUM($self->{columns}{names}[$i]);
755
}elsif($self->{totals}{$self->{columns}{names}[$i]}{operation} eq "AVG"){
756
0
$total = $self->AVG($self->{columns}{names}[$i]);
757
}elsif($self->{totals}{$self->{columns}{names}[$i]}{operation} eq "COUNT"){
758
0
$total = $self->COUNT($self->{columns}{names}[$i]);
759
}
760
}
761
762
#Formatos
763
0
0
if($self->{totals}{$self->{columns}{names}[$i]}{format} eq "price"){
764
1
1
11
use Number::Format;
1
2
1
429
765
0
my $NF = Number::Format->new(%{$self->{Number_Format}});
0
766
0
$total = $NF->format_price($total);
767
}
768
769
0
0
if($self->{totals}{$self->{columns}{names}[$i]}{label}){
770
0
my $total_label = $total;
771
0
$total = $self->{totals}{$self->{columns}{names}[$i]}{label};
772
0
$total =~ s/%%/$total_label/g;
773
}
774
0
push(@totals,$total);
775
}
776
777
0
return " " . Tr ({},td({colspan=>scalar(@{$self->{group_fields_array}})},
0
778
'' .
779
Tr ($self->{totals}{Tr}{params},[td($self->{totals}{td}{params},\@totals)]) . "\n" .
780
'
'
781
)) . "\n";
782
}
783
784
sub print_group_item_totals {
785
0
0
0
my $self = shift;
786
0
my $field = shift;
787
0
my $field_value = shift;
788
0
my $totals = "";
789
0
foreach my $i(0 .. (($self->{colspan})- scalar(@{$self->{group_fields_array}}))) {
0
790
# if(!(defined $self->{group_totals}{$self->{columns}{names}[$i]})){
791
# $totals .= ' ';
792
# next;
793
# }
794
#Operaciones
795
0
my $total = "";
796
0
0
if(defined $self->{group_totals}{$self->{columns}{names}[$i]}{operation}){
797
0
0
if($self->{group_totals}{$self->{columns}{names}[$i]}{operation} eq "SUM"){
0
0
798
0
$total = $self->group_SUM($self->{columns}{names}[$i],$field,$field_value);
799
}elsif($self->{group_totals}{$self->{columns}{names}[$i]}{operation} eq "AVG"){
800
0
$total = $self->group_AVG($self->{columns}{names}[$i],$field,$field_value);
801
}elsif($self->{group_totals}{$self->{columns}{names}[$i]}{operation} eq "COUNT"){
802
0
$total = $self->group_COUNT($self->{columns}{names}[$i],$field,$field_value);
803
}
804
}
805
806
#Formatos
807
0
0
if($self->{group_totals}{$self->{columns}{names}[$i]}{format} eq "price"){
808
1
1
6
use Number::Format;
1
2
1
915
809
0
my $NF = Number::Format->new(%{$self->{Number_Format}});
0
810
0
$total = $NF->format_price($total);
811
}
812
813
0
0
if($self->{group_totals}{$self->{columns}{names}[$i]}{label}){
814
0
my $total_label = $total;
815
0
$total = $self->{group_totals}{$self->{columns}{names}[$i]}{label};
816
0
$total =~ s/%%/$total_label/g;
817
}
818
0
0
if(defined $self->{columns_align}){
819
0
$self->{group_item_totals}{td}{params}{align} = $self->{columns_align}[$i];
820
0
$totals .= td($self->{group_item_totals}{td}{params},$total);
821
}else{
822
0
$totals .= td($self->{group_item_totals}{td}{params},$total);
823
}
824
}
825
0
return " " . Tr ($self->{group_item_totals}{Tr}{params},$totals) . "\n";
826
}
827
828
sub SUM {
829
0
0
0
my $self = shift;
830
0
0
my $field = shift || "";
831
0
0
return 0 if(!$field);
832
0
my $total = 0;
833
0
foreach my $rec(@{$self->{rs}}) {
0
834
0
$total += $rec->{$field};
835
}
836
0
return $total;
837
}
838
839
sub group_SUM {
840
0
0
0
my $self = shift;
841
0
0
my $field = shift || "";
842
0
my $filter = shift;
843
0
my $filter_value = shift;
844
0
0
return 0 if(!$field);
845
0
my $total = 0;
846
0
foreach my $rec(@{$self->{rs}}) {
0
847
0
0
next if($rec->{$filter} ne $filter_value);
848
0
$total += $rec->{$field};
849
}
850
0
return $total;
851
}
852
853
sub COUNT {
854
0
0
0
my $self = shift;
855
0
0
my $field = shift || "";
856
0
0
return 0 if(!$field);
857
0
return scalar( @{$self->{rs}});
0
858
}
859
860
sub group_COUNT {
861
0
0
0
my $self = shift;
862
0
0
my $field = shift || "";
863
0
my $filter = shift;
864
0
my $filter_value = shift;
865
0
0
return 0 if(!$field);
866
0
my $total = 0;
867
0
foreach my $rec(@{$self->{rs}}) {
0
868
0
0
next if($rec->{$filter} ne $filter_value);
869
0
$total += 1;
870
}
871
0
return $total;
872
}
873
874
sub AVG {
875
0
0
0
my $self = shift;
876
0
0
my $field = shift || "";
877
0
0
return 0 if(!$field);
878
0
my $avg = 0;
879
0
my $it = 0;
880
881
0
foreach my $rec(@{$self->{rs}}) {
0
882
0
$it++;
883
0
$avg += $rec->{$field};
884
}
885
886
0
eval {
887
0
$avg = $avg / $it;
888
};
889
890
0
0
if($@){
891
0
$avg = "";
892
}
893
894
0
$avg = neares(.01,$avg);
895
0
return $avg;
896
}
897
898
sub group_AVG {
899
0
0
0
my $self = shift;
900
0
0
my $field = shift || "";
901
0
my $filter = shift;
902
0
my $filter_value = shift;
903
0
0
return 0 if(!$field);
904
0
my $avg = 0;
905
0
my $it = 0;
906
907
0
foreach my $rec(@{$self->{rs}}) {
0
908
0
0
next if($rec->{$filter} ne $filter_value);
909
0
$it++;
910
0
$avg += $rec->{$field};
911
}
912
913
0
eval {
914
0
$avg = $avg / $it;
915
};
916
917
0
0
if($@){
918
0
$avg = "";
919
}
920
921
0
$avg = neares(.01,$avg);
922
0
return $avg;
923
}
924
925
sub headers_groups {
926
0
0
0
my $self = shift;
927
0
$self->{headers_groups} = shift;
928
}
929
930
sub orders {
931
0
0
0
my $self = shift;
932
0
$self->{orders} = shift;
933
0
0
if($self->{orders}->{param("cg_order")}){
934
0
$self->{sql}{order_by} = $self->{orders}->{param("cg_order")};
935
0
0
$self->{sql}{order_by} .= " DESC " if (param("cg_side"));
936
0
0
$self->{sql}{order_by} .= " ASC " if (!param("cg_side"));
937
}
938
}
939
940
941
942
=head1 SYNOPSIS
943
944
Easily create html lists whit auto order, auto pagination, grouping and conditional formats.
945
946
Perhaps a little code snippet.
947
948
use CGI::List;
949
950
#We need a DBH Handle
951
$dbh = DBI->connect(.....);
952
953
#Create List Object
954
$list = CGI::List->new(
955
dbh => $dbh,
956
sql => {
957
select => "foo, bar ",
958
from => "table1",
959
limit => "20",
960
where => "some_column1=? AND some_column2=?",
961
params=>["Value1","Value2"],
962
order_by => "foo DESC",
963
},
964
);
965
966
#Print
967
print $list->print();
968
969
=head1 FEATURES
970
971
* Auto Order
972
* Auto Pagination
973
* CSS based. Contact developer for CSS examples
974
* Column totals(Only SUM, COUNT and AVG are supported)
975
* Conditional formats for rows
976
* Conditional Formats for cells
977
* Auto detect column names
978
* 2 row formats for better visualization
979
* Row grouping
980
* Http Link and highlight on rows based in rows keys
981
* Opener action for pop up windows
982
* And more
983
984
=head1 METHODS
985
986
=head2 new()
987
988
This method creates a new $list object, which you then use to generate and process your list.
989
990
my $list = CGI::List->new();
991
992
The following is a description of each option, in alphabetical order:
993
994
name => 'list_name'
995
If you use a multi lists pages you need to specify a name for each list
996
on_errors => 'print',
997
If you have SQL errors you can print(default), warn or die
998
debug => 0 | 1, default 0
999
If is set to 1 this print the query executed on SQL errors
1000
caption => 'list title'
1001
This create a list title with the caption html tag
1002
auto_order => 1 | 0, default 1
1003
Enable, disable auto order mechanism on the list
1004
pagination => 1 | 0, default 1
1005
Enable or disable auto pagination on the list
1006
nav_pages => $number, default 4
1007
Number of pages you can see on pagination
1008
Number_Format => {THOUSANDS_SEP=>",",DECIMAL_POINT=>".",MON_THOUSANDS_SEP=>",","MON_DECIMAL_POINT"=>".","INT_CURR_SYMBOL"=>'$'};
1009
On SUM otions you can format the result to price ($1,234.00), whit this parameters THOUSANDS_SEP, DECIMAL_POINT, MON_THOUSANDS_SEP, MON_DECIMAL_POINT, INT_CURR_SYMBOL.
1010
1011
table => {}
1012
Propiedades de la tabla, default {width => "100%",class => "cg_table",align => "center",cellpadding=>"0",cellspacing=>"0"}
1013
labels => {
1014
page_of => 'Page _PAGE_ of _OF_',
1015
no_data => 'No records found',
1016
link_up => '↑',
1017
link_down => '↓',
1018
next_page => '»',
1019
previous_page => '«',
1020
number_of_rows => "_NUMBER_ rows",
1021
};
1022
This are the text printed on the list, you can traslate to other language
1023
1024
1025
1026
=head2 print()
1027
1028
This function renders the list into HTML, and returns a string containing the list.
1029
1030
print $list->print;
1031
1032
=head2 group()
1033
1034
This method Create groups of data:
1035
1036
$list->group(key=>'key_field',fields=>[qw/key_field other_field other_field/]);
1037
1038
=head2 group_total()
1039
1040
This method calculate row totals on each group:
1041
1042
$list->group_total(key=>'key_field',type=>"MATH",operation=>'SUM',label=>"%% some text",format=>'price');
1043
Operation support only SUM, AVG, and COUNT, the format parameter are optional
1044
1045
=head2 total()
1046
1047
This method calculate row totals:
1048
1049
$list->total(key=>'key_field',type=>"MATH",operation=>'SUM',label=>"%% some text",format=>'price');
1050
Operation suport only SUM, AVG, and COUNT, the format parameter are optional
1051
1052
=head2 row_format()
1053
1054
This function specify a format of row depending on their value
1055
1056
$list->row_format(name=>"field_name",condition=>"'%%' eq 'urgent'",params=>{class=>"cg_row_urgent"});
1057
1058
%% is the cell value, on this example you need to create 2 css class cg_row_urgent and cg_row_urgent_hover
1059
for the hover action
1060
1061
=head2 cell_format();
1062
1063
This function specify a format of cell depending on their value
1064
1065
$list->cell_format(name=>"field_name",condition=>"'%%' eq 'urgent'",params=>{class=>"cg_cell_urgent"});
1066
1067
%% is the cell value, on this example you need to create 2 css class cg_cell_urgent and cg_cell_urgent_hover
1068
for the hover action
1069
1070
=head2 columns_width()
1071
1072
This function specify the width of each column
1073
1074
$list->columns_width(["100","200","300"]);
1075
1076
On this example you have a 3 columns query and 100, 200, 300 are the width of each column
1077
1078
=head2 columns_align()
1079
1080
This function specify the horizontal align of each column
1081
1082
$list->columns_align(["left","center","right"]);
1083
1084
On this example you have a 3 columns query and left, center, right are the alignment of each column data
1085
1086
=head2 columns_headers_align()
1087
1088
This function specify the horizontal align of each column header
1089
1090
$list->columns_headers_align(["left","center","right"]);
1091
1092
On this example you have a 3 columns query and left, center, right are the alignment of each column header data
1093
1094
=head1 Examples
1095
1096
This example provides an list of data with auto order, auto pagination and action on each row click
1097
1098
my $list = CGI::List->new(
1099
dbh => $dbh,
1100
name => "pays_list",
1101
sql => {
1102
select => "p.pay_id, p.date, pr.name, " .
1103
"IF(p.is_cancel,'Cancel','Active') AS 'status'",
1104
from => "pays p INNER JOIN partners pr ON p.pay_id=pr.pay_id ",
1105
limit => "20",
1106
where => "some_column=? AND some_column=?",
1107
params=>["Value1","Value2"],
1108
order_by => "p.date DESC",
1109
},
1110
link => {
1111
key => "pay_id",
1112
hidde_key_col => 1,
1113
location => "pays.pl",
1114
transit_params => {some_param_to_be_present_everywere=>"value"},
1115
},
1116
);
1117
$list->print();
1118
1119
1120
=head1 AUTHOR
1121
1122
David Romero Garcia, C<< >>
1123
1124
=head1 COLABORATORS
1125
1126
Juan C. Sanchez-DelBarrio
1127
1128
=head1 BUGS
1129
1130
Please report any bugs or feature requests to
1131
C, or through the web interface at
1132
L.
1133
I will be notified, and then you'll automatically be notified of progress on
1134
your bug as I make changes.
1135
1136
=head1 SUPPORT
1137
1138
You can find documentation for this module with the perldoc command.
1139
1140
perldoc CGI::List
1141
1142
You can also look for information at:
1143
1144
L.
1145
L.
1146
1147
=over 4
1148
1149
=item * AnnoCPAN: Annotated CPAN documentation
1150
1151
L
1152
1153
=item * CPAN Ratings
1154
1155
L
1156
1157
=item * RT: CPAN's request tracker
1158
1159
L
1160
1161
=item * Search CPAN
1162
1163
L
1164
1165
=back
1166
1167
=head1 ACKNOWLEDGEMENTS
1168
1169
=head1 COPYRIGHT & LICENSE
1170
1171
Copyright 2007 David Romero GarcĂa, all rights reserved.
1172
1173
This program is free software; you can redistribute it and/or modify it
1174
under the same terms as Perl itself.
1175
1176
=cut
1177
1178
1; # End of CGI::List