[Bio] / FortyEight / Table.pm Repository:
ViewVC logotype

Diff of /FortyEight/Table.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1, Tue Jan 16 20:36:03 2007 UTC revision 1.2, Fri Feb 23 19:44:21 2007 UTC
# Line 6  Line 6 
6    
7  1;  1;
8    
 =over 3  
   
 =head1 NAME  
   
 Table  
   
 =head1 DESCRIPTION  
   
 The Table Component implements an HTML/javascript table for displaying, filtering and browsing data.  
 It supports onClick events and popup menus for each cell. Data can also be grouped by a single column.  
 Like all WebApplicationComponents, configuration of columns to display is also supported.  
   
 =head1 ARGUMENTS  
   
 Arguments are passed as a single hash. All data must be passed as references (i.e. reference to an array  
 instead of an array). A table is instanciated via the I<new> method.  
   
 =head2 Mandatory Arguments  
   
 =item B<data>  
   
 This must be an array of rows, each containing an array of cells. The data type of the cell contents is  
 detected for sorting issues. The first cell in a column will determine the data type. Three types of data  
 are differentiated:  
   
 Integers and Floats  
 Dates in the format mm/dd/yyyy  
 Strings  
   
 The cell data must not include quotation marks or linebreaks of any kind.  
   
 =item B<columns>  
   
 The columns are passed as an array of column headers, also no quotation marks or linebreaks are allowed.  
   
 =head2 Optional Arguments  
   
 =item B<id>  
   
 The identification of the table. Only neccessary if you have more than one table on a single page. Default is  
 'table'.  
   
 =item B<image_base>  
   
 The directory relative to the cgi directory where all images are stored. 'clear.gif' needs to be present in this  
 directory. Default is '../images'.  
   
 =item B<offset>  
   
 The array index of the first item in the list to be displayed. Default is 0.  
   
 =item B<perpage>  
   
 Number of items to be displayed on each page. Default is 20.  
   
 =item B<show_perpage>  
   
 Boolean to determine whether the user may change the number of items to be displayed on each  
 page. Default is false.  
   
 =item B<show_topbrowse>  
   
 Boolean to determine whether the browsing functions are displayed above the table. Default is  
 false.  
   
 =item B<show_bottombrowse>  
   
 Boolean to determine whether the browsing functions are displayed below the table. Default is  
 false.  
   
 =item B<enable_grouping>  
   
 Boolean to determine whether the grouping of a single column should be supported. Grouped  
 columns are collapsed if they contain consecutive identical values. They can be expanded  
 and collapsed by the user via a click on the symbol in the according cell. Default is false.  
   
 =item B<group_col>  
   
 Array index of the column to be the grouping column. Default is 0.  
   
 =item B<sortable>  
   
 Boolean to determine whether the user is allowed to sort the columns. Default is false.  
   
 =item B<show_filter>  
   
 Boolean to determine whether the user should be able to filter the columns. Default is false.  
   
 =item B<available_operators>  
   
 An array of operators available for filtering. Must be passed in the following format, which  
 is also the default:  
   
  ( [ 'like', '&cong;' ],  
   [ 'unlike', '!&cong;' ],  
   [ 'equal', '=' ],  
   [ 'unequal', '!=' ],  
   [ 'less', '&lt;' ],  
   [ 'more', '&gt;' ] )  
   
 Where the first entry is the operator and the second entry is the html to be displayed in the  
 select box.  
   
 =item B<preselected_operators>  
   
 A hash containing the column names as key and the operator to be pre-selected as a value. As  
 default, the first operator in the list is selected.  
   
 =item B<operands>  
   
 A hash containing the column names as key and the operand as values. If show_filter is true,  
 columns which are not a key of this hash will not receive a filter box.  
   
 =item B<onclicks>  
   
 If passed, this must be an array of rows, each containing an array of cells with the same  
 dimensions as the data array. The values should be urls that a click on the according cell  
 should link to.  
   
 =item B<popup_menu>  
   
 A hash containing the keys 'titles', 'infos' and 'menus'. Each of these have an array of arrays,  
 matching the dimensions of the data array, as a value. For usage of the popup menu, consult  
 the popup menu manual.  
   
 =back  
   
 =cut  
   
9  # initialize the table  # initialize the table
10  sub new {  sub new {
11    my ($params) = @_;    my ($params) = @_;
# Line 198  Line 69 
69    my $show_perpage      = $params->{show_perpage}      || 0;    my $show_perpage      = $params->{show_perpage}      || 0;
70    my $show_topbrowse    = $params->{show_topbrowse}    || 0;    my $show_topbrowse    = $params->{show_topbrowse}    || 0;
71    my $show_bottombrowse = $params->{show_bottombrowse} || 0;    my $show_bottombrowse = $params->{show_bottombrowse} || 0;
72    my $group_col         = $params->{group_col}         || 0;    my $group_cols        = $params->{group_cols}        || {};
   my $enable_grouping   = $params->{enable_grouping}   || 0;  
73    my $sortable          = $params->{sortable}          || 0;    my $sortable          = $params->{sortable}          || 0;
74      my $sortcols          = $params->{sortcols}          || { 'all' => 1 };
75      my $control_menu      = $params->{control_menu};
76    my $column_widths     = $params->{column_widths};    my $column_widths     = $params->{column_widths};
77      my $collapsed_columns = $params->{collapsed_columns} || {};
78    unless (defined($column_widths)) {    unless (defined($column_widths)) {
79      foreach (@columns) {      foreach (@columns) {
80        push(@$column_widths, -1);        push(@$column_widths, -1);
# Line 305  Line 178 
178    $data_source =~ s/'/\@1/g;    $data_source =~ s/'/\@1/g;
179    $data_source =~ s/"/\@2/g;    $data_source =~ s/"/\@2/g;
180    
181      # get the groupcol information
182      my @group_cols_array;
183      my $num_groupcols = 0;
184      for (my $i=0; $i<scalar(@columns); $i++) {
185        if (exists($group_cols->{$i})) {
186          push(@group_cols_array, 1);
187          $num_groupcols++;
188        } else {
189          push(@group_cols_array, 0);
190        }
191      }
192    
193    # insert hidden fields    # insert hidden fields
194    $table .= "\n<input type='hidden' id='table_data_" . $id . "' value='" . $data_source . "'>\n";    $table .= "\n<input type='hidden' id='table_data_" . $id . "' value='" . $data_source . "'>\n";
195    $table .= "<input type='hidden' id='table_onclicks_" . $id . "' value='" . $onclicks . "'>\n";    $table .= "<input type='hidden' id='table_onclicks_" . $id . "' value='" . $onclicks . "'>\n";
# Line 316  Line 201 
201    $table .= "<input type='hidden' id='table_rows_" . $id . "' value='" .  $total . "'>\n";    $table .= "<input type='hidden' id='table_rows_" . $id . "' value='" .  $total . "'>\n";
202    $table .= "<input type='hidden' id='table_cols_" . $id . "' value='" . scalar(@columns) . "'>\n";    $table .= "<input type='hidden' id='table_cols_" . $id . "' value='" . scalar(@columns) . "'>\n";
203    $table .= "<input type='hidden' id='table_start_" . $id . "' value='0'>\n";    $table .= "<input type='hidden' id='table_start_" . $id . "' value='0'>\n";
204      $table .= "<input type='hidden' id='table_numgroups_" . $id . "' value='" . $num_groupcols . "'>\n";
205      $table .= "<input type='hidden' id='table_groups_" . $id . "' value='" . join(';', @group_cols_array) . "'>\n";
206    $table .= "<input type='hidden' id='table_sortdirection_" . $id . "' value='up'>\n";    $table .= "<input type='hidden' id='table_sortdirection_" . $id . "' value='up'>\n";
207    
208    # check for title    # check for title
# Line 329  Line 216 
216      $table_width = "width: " . $params->{table_width} . "px;";      $table_width = "width: " . $params->{table_width} . "px;";
217    }    }
218    
219      # check for control menu
220      if ($control_menu) {
221    
222        # surrounding table
223        $table .= "<table><tr><td>";
224    
225        # control tree columns
226        $table .= "<table><tr><td>Visible Tree Columns</td></tr>";
227        my @sorted_keys = sort(keys(%$group_cols));
228        foreach my $key (@sorted_keys) {
229          my $colname = $columns[$key];
230          $table .= "<tr><td>$colname</td><td><input type='checkbox' name='" . $key  ."_vis' id='table_" . $id . "_" . $key  ."_vis' checked=checked></td></tr>";
231        }
232        $table .= "</table></td><td>";
233    
234        # control data columns
235        $table .= "<div style='height: 250px; overflow: auto;'><table><tr><td>Visible Data Columns</td></tr>";
236        for (my $i=0; $i<scalar(@columns); $i++) {
237          unless ($group_cols->{$i}) {
238            $table .= "<tr><td>" . $columns[$i] . "</td><td><input type='checkbox' name='" . $i  ."_vis' id='table_" . $id . "_" . $i  ."_vis'></td></tr>";
239          }
240        }
241        $table .= "</table></div>";
242    
243        $table .= "</td></tr></table><input type='button' value='Apply' onclick='reload_table(\"" . $id . "\");'><input type='button' value='Show Data' onclick='switch_data_tree(\"" . $id . "\");' id='table_" . $id . "_switch_button'>";
244      }
245    
246    # check for display options - select entries per page    # check for display options - select entries per page
247    if ($show_perpage) {    if ($show_perpage) {
248      $table .= "<table class='table_table' style='$table_width'>\n<tr><td align=center><span class='table_perpage'>display&nbsp;<input type='text' id='table_perpage_" . $id . "' name='table_perpage_" . $id . "' size='3' value='" . $perpage . "' onkeypress='check_submit_filter(event, \"" . $id . "\")'>&nbsp;items per page</span></td></tr>\n";      $table .= "<table class='table_table' style='$table_width'>\n<tr><td align=center><span class='table_perpage'>display&nbsp;<input type='text' id='table_perpage_" . $id . "' name='table_perpage_" . $id . "' size='3' value='" . $perpage . "' onkeypress='check_submit_filter(event, \"" . $id . "\")'>&nbsp;items per page</span></td></tr>\n";
# Line 346  Line 260 
260    # start data table    # start data table
261    $table .= "<tr><td><table id='table_" . $id . "' class='table_table' style='$table_width'>";    $table .= "<tr><td><table id='table_" . $id . "' class='table_table' style='$table_width'>";
262    
   # check for display options - display column filters  
   if ($complex_filter) {  
     if (scalar(keys(%operands)) > 0) {  
       $table .= "<tr>";  
   
       # check each value for an existing filter field  
       my $i = 0;  
       foreach my $col (@columns) {  
         if (exists($operands{$col})) {  
   
           # check if there is a preselected value for this filter field  
           my $preselected_operand = "";  
           if (defined($operands{$col})) {  
             $preselected_operand = $operands{$col};  
           }  
   
           # check for filter comparison operator  
           $table .= "<td><select name='" . $id . "_" . $col . "_operator' id='table_" . $id . "_operator_" . $i . "'>";  
   
           foreach my $operator (@available_operators) {  
             my $preselected_operator = "";  
   
             if (defined($preselected_operators{$col})) {  
               if ($preselected_operators{$col} eq $operator->[0]) {  
                 $preselected_operator = " selected='selected'";  
               }  
             }  
   
             $table .= "<option value='" . $operator->[0] . "'" . $preselected_operator . ">" . $operator->[1] . "</option>";  
           }  
           $table .= "</select><input type='text' name='" . $id . $col . "' class='filter_item' value='" . $preselected_operand . "'  id='table_" . $id . "_operand_" . $i . "' onkeypress='check_submit_filter(event, \"" . $id . "\")'></td>";  
         } else {  
           $table .= "<td></td>";  
         }  
         $i++;  
       }  
   
       $table .= "</tr>";  
     }  
   }  
   
263    # write table header    # write table header
264    $table .= "<tr>";    $table .= "<tr>";
265    my $i = 1;    my $i = 1;
# Line 408  Line 281 
281      # prepare html for sorting according to column      # prepare html for sorting according to column
282      my $order_img = "<a href='javascript: table_sort(\"" . $id . "\", \"" . $i . "\", \"ASC\");' class='table_first_row' title='Click to sort'>";      my $order_img = "<a href='javascript: table_sort(\"" . $id . "\", \"" . $i . "\", \"ASC\");' class='table_first_row' title='Click to sort'>";
283    
284      # create config button      # create row collapse/expand button
285      my $conf_button = qq~<span style="background-color: white; border: 1px solid black; font-size: 7pt; padding: 1px; cursor: pointer; width: 13px; vertical-align: top; text-align: left;" class="hideme" onclick="change_group('$id\_col_$i');" id="$id\_col_$i" name="conf">+/-</span>~;      my $collapse_button = "";
286        if ($group_cols->{$i - 1}) {
287          if ($collapsed_columns->{$col}) {
288            $collapse_button = "<img src='./Html/plus.gif' id='table_collapse_" . $id . "_" . ($i - 1) . "' onclick='expand_column(\"" . $id . "\", \"" . ($i - 1) . "\");'>";
289          } else {
290            $collapse_button = "<img src='./Html/minus.gif' id='table_collapse_" . $id . "_" . ($i - 1) . "' onclick='expand_column(\"" . $id . "\", \"" . ($i - 1) . "\");'>";
291          }
292        }
293    
294      # check for simple filter      # check for simple filter
295      my $filter = "";      my $filter = "";
296      if (defined($operands{$col})) {      if (defined($operands{$col})) {
297        $filter = "<br/><input type=hidden name='" . $id . "_" . $col . "_operator' value='like' id='table_" . $id . "_operator_" . $i . "'><input type='text' name='" . $id . $col . "' class='filter_item' value='' size=5 id='table_" . $id . "_operand_" . $i . "' onkeypress='check_submit_filter(event, \"" . $id . "\")' style='width: 100%;' title='Enter Search Text'>";        if ($complex_filter) {
298    
299            # check if there is a preselected value for this filter field
300            my $preselected_operand = "";
301            if (defined($operands{$col})) {
302              $preselected_operand = $operands{$col};
303            }
304    
305            # check for filter comparison operator
306            $filter = "<br/><select name='" . $id . "_" . $col . "_operator' id='table_" . $id . "_operator_" . $i . "' style='width: 40px;'>";
307    
308            foreach my $operator (@available_operators) {
309              my $preselected_operator = "";
310    
311              if (defined($preselected_operators{$col})) {
312                if ($preselected_operators{$col} eq $operator->[0]) {
313                  $preselected_operator = " selected='selected'";
314                }
315              }
316    
317              $filter .= "<option value='" . $operator->[0] . "'" . $preselected_operator . ">" . $operator->[1] . "</option>";
318            }
319            $filter .= "</select><input type='text' name='" . $id . $col . "' class='filter_item' value='" . $preselected_operand . "'  id='table_" . $id . "_operand_" . $i . "' onkeypress='check_submit_filter(event, \"" . $id . "\")' style='width: 70%;'>";
320          } else {
321            my $operator = 'like';
322            if (defined($preselected_operators{$col})) {
323              $operator = $preselected_operators{$col};
324            }
325            $filter = "<br/><input type=hidden name='" . $id . "_" . $col . "_operator' value='" . $operator . "' id='table_" . $id . "_operator_" . $i . "'><input type='text' name='" . $id . $col . "' class='filter_item' value='' size=5 id='table_" . $id . "_operand_" . $i . "' onkeypress='check_submit_filter(event, \"" . $id . "\")' style='width: 100%;' title='Enter Search Text'>";
326          }
327      }      }
328    
329      # check if colum header click should sort      # check if colum header click should sort
330      if ($sortable) {      if ($sortable) {
331        $table .= "<td name='" . $name . "' class='table_first_row' style='" . $colwidths->[$i - 1] . "'>" . $conf_button . $order_img . $col . "&nbsp;<img src='./Html/up-arrow.gif'><img src='./Html/down-arrow.gif'></a>" . $filter . "</td>";        if ($sortcols->{$i} || $sortcols->{'all'}) {
332            $table .= "<td name='" . $name . "' class='table_first_row' style='" . $colwidths->[$i - 1] . "'>" . $collapse_button . $order_img . $col . "&nbsp;<img src='./Html/up-arrow.gif'><img src='./Html/down-arrow.gif'></a>" . $filter . "</td>";
333          }
334      } else {      } else {
335        $table .= "<td name='" . $name . "' class='table_first_row' style='" . $colwidths->[$i - 1] . "'>" . $conf_button . $col . $filter . "</td>";        $table .= "<td name='" . $name . "' class='table_first_row' style='" . $colwidths->[$i - 1] . "'>" . $collapse_button . $col . $filter . "</td>";
336      }      }
337    
338      # increase column counter      # increase column counter
# Line 471  Line 382 
382      $to = $total;      $to = $total;
383    }    }
384    
385    $browse .= "<tr><td><table class='table_browse'><tr><td align='left' width='20%'>" . $left . "</td><td align='center' width='60%'>displaying <input type='text' name='table_start_" . $id . "' class='disp' readonly=1 value='" . ($offset + 1) . "'> - <input type='text' name='table_stop_" . $id . "' class='disp' readonly=1 value='" . $to . "'> of <input type='text' name='table_total_" . $id . "' class='disp' readonly=1 value='" . $total . "'></td><td align='right' width='20%'>" . $right . "</td></tr></table></td></tr>";    $browse .= "<tr><td><table class='table_browse'><tr><td align='left' width='20%'>" . $left . "</td><td align='center' width='60%'>displaying <span name='table_start_" . $id . "'>" . ($offset + 1) . "</span> - <span name='table_stop_" . $id . "'>" . $to . "</span> of <span name='table_total_" . $id . "'>" . $total . "</span></td><td align='right' width='20%'>" . $right . "</td></tr></table></td></tr>";
386    
387    return $browse;    return $browse;
388  }  }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3