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


" if($self->{caption});
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}
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