App-Widget

 view release on metacpan or  search on metacpan

lib/App/Widget/DataTable.pm  view on Meta::CPAN


######################################################################
## $Id: DataTable.pm 12437 2009-01-14 14:26:36Z spadkins $
######################################################################

package App::Widget::DataTable;
$VERSION = (q$Revision: 12437 $ =~ /(\d[\d\.]*)/)[0];  # VERSION numbers generated by svn

use App;
use App::Widget;
@ISA = ( "App::Widget" );

use strict;

=head1 NAME

App::Widget::DataTable - An HTML table which serves as a repository table viewer/editor

=head1 SYNOPSIS

   use App::Widget::DataTable;

   $name = "get_data";
   $w = App::Widget::DataTable->new($name);
   print $w->html();

=cut

######################################################################
# CONSTANTS
######################################################################

######################################################################
# ATTRIBUTES
######################################################################
# {border}            = 0;
# {cellspacing}       = 2;
# {cellpadding}       = 0;
# {width}             = "";
# {bgcolor}           = "";
# {nowrap}            = "1";
# {font_face}         = "verdana,geneva,arial,sans-serif";
# {font_size}         = "-2";
# {font_color}        = "";
# {heading_bgcolor}   = "#cccccc";
# {heading_nowrap}    = 0;
# {heading_align}     = 0;
# {heading_valign}    = 0;
# {column_selectable} = 1;
# {row_selectable}    = 0;
# {row_single_selectable} = 0;
# {columns}           = [ "Name", "Address", "City", "State", "Country", "Home Phone" ];
# {headings}          = [ "Name", "Address", "City", "State", "Country", "Home Phone" ];
# {data}              = [ [ "Smith, Harold", "1215 Interloke Pass", "Jonesboro", "GA", "US", "770-603-1810" ],
#                         [ "Smith, Mike",   "1215 Interloke Pass", "Jonesboro", "GA", "US", "770-603-1811" ],
#                         [ "Smith, Sarah",  "1215 Interloke Pass", "Jonesboro", "GA", "US", "770-603-1812" ],
#                         [ "Smith, Ken",    "1215 Interloke Pass", "Jonesboro", "GA", "US", "770-603-1813" ],
#                         [ "Smith, Mary",   "1215 Interloke Pass", "Jonesboro", "GA", "US", "770-603-1814" ], ];
# {startrow}          = 1
# {maxrows}           = 20
# {scrollable}        = 0;
# {sortable}          = 0;
# {filterable}        = 0;
# {editable}          = 0;

# INPUTS FROM THE ENVIRONMENT

=head1 DESCRIPTION

This class is a <input type=submit> HTML element.
In the advanced configurations, it is rendered as an image button.

=cut

######################################################################
# INITIALIZATION
######################################################################

sub _init {
    &App::sub_entry if ($App::trace);
    my $self = shift;
    $self->SUPER::_init(@_);
    $self->{table} = $self->{name} if (!$self->{table});

    $self->{context}->dbgprint("DataTable->init()")
        if ($App::DEBUG && $self->{context}->dbg(1));
}

######################################################################
# EVENTS
######################################################################

# Usage: $widget->handle_event($event, @args);
sub handle_event {
    &App::sub_entry if ($App::trace);
    my ($self, $wname, $event, @args) = @_;
    my ($name, $context, $colnum, $x, $y, $startrow, $maxrows, $width, $direction);

    #$self->clear_messages();

    $name = $self->{name};
    $self->{context}->dbgprint("DataTable($name)->handle_event($wname,$event,@args)")
        if ($App::DEBUG && $self->{context}->dbg(1));

lib/App/Widget/DataTable.pm  view on Meta::CPAN

            }
            else {
                $value = $context->so_get($var);
                $value = join(",", @$value) if (ref($value) eq "ARRAY");
                if (defined $value) {
                    $phrase =~ s/\{$var\}/$value/g;
                }
                else {
                    $phrase = "";
                }
            }
        }
        if ($phrase eq "") {
            $text =~ s/^\[[^\[\]]+\]\n?$//;  # zap it including (optional) ending newline
        }
        else {
            $text =~ s/^\[[^\[\]]+\]$/$phrase/;
        }
    }
    while ( $text =~ /\{([^\{\}]+)\}/ ) {  # vars of the form {var}
        $var = $1;
        if (defined $values->{$var}) {
            $value = $values->{$var};
            $value = join(",", @$value) if (ref($value) eq "ARRAY");
            $text =~ s/\{$var\}/$value/g;
        }
        else {
            $value = $context->so_get($var);
            $value = join(",", @$value) if (ref($value) eq "ARRAY");
        }
        $value = "" if (!defined $value);
        $text =~ s/\{$var\}/$value/g;
    }
    &App::sub_exit($text) if ($App::trace);
    $text;
}

######################################################################
# OUTPUT METHODS
######################################################################

sub table_html {
    &App::Widget::DataTable::html(@_);
}

sub html {
    &App::sub_entry if ($App::trace);
    my $self = shift;
    $self->{context}->dbgprint("DataTable->html()")
        if ($App::DEBUG && $self->{context}->dbg(1));

    my ($context, $name, $data);
    $context   = $self->{context};
    $name = $self->{name};

    my ($key, $column);

    my ($numcols, $table, $title);
    my ($width, $border, $cellspacing, $cellpadding);
    my ($bgcolor, $align, $valign, $nowrap);
    my ($font_face, $font_size, $font_color);
    my ($heading_bgcolor, $heading_align, $heading_valign, $heading_nowrap);
    my ($columns, $headings, $scrollable, $sortable, $filterable, $editable);
    my ($startrow, $numrow, $numbered);
    my ($keys, $mode, $sql);
    my ($column_selectable, $row_selectable, $row_single_selectable, $elem_selected, $single_row_select);
    my (@edit_style, @column_length);
    my ($rowactions, $rowactiondefs, $rowaction, $rowactiondef);
    my (@select_actions, @single_select_actions, @row_actions);

    $table             = $self->get("table");
    return "No table defined." if (!$table);
    $columns           = $self->get_columns();
    return "No columns defined for table [$table]. (maybe it doesn't exist)" if (!$columns || $#$columns == -1);
    $headings          = $self->get_headings();
    $data              = $self->get_data();
    $startrow          = $self->get("startrow",         1);
    $title             = $self->get("title");
    $width             = $self->get("width");
    $bgcolor           = $self->get("bgcolor");
    $font_color        = $self->get("font_color");
    $border            = $self->get("border",           0);
    $cellspacing       = $self->get("cellspacing",      2);
    $cellpadding       = $self->get("cellpadding",      2);
    $align             = $self->get("align",            "");
    $valign            = $self->get("valign",           "top");
    $nowrap            = $self->get("nowrap",           1);
    $font_face         = $self->get("font_face",         "verdana,geneva,arial,sans-serif");
    $font_size         = $self->get("font_size",         -2);
    $heading_bgcolor   = $self->get("heading_bgcolor",   "#cccccc");
    $heading_align     = $self->get("heading_align",     $align);
    $heading_valign    = $self->get("heading_valign",    "bottom");
    $heading_nowrap    = $self->get("heading_nowrap",    $nowrap);
    $mode              = $self->get("mode",             "view");
    $scrollable        = $self->get("scrollable",       0);
    $sortable          = $self->get("sortable",         0);
    $filterable        = $self->get("filterable",       0);
    $editable          = $self->get("editable",         0);
    $numbered          = $self->get("numbered",         1);
    $column_selectable = $self->get("column_selectable", 1);
    $row_selectable    = $self->get("row_selectable",    (($mode eq "edit") ? 1 : 0));
    $row_single_selectable = $self->get("row_single_selectable", 0);
    $keys              = $self->get("keys");
    $sql               = $self->get("sql");
    $rowactions        = $self->get("rowactions");
    $rowactiondefs     = $self->get("rowaction");

    my $repname = $self->get("repository");
    my $rep = $context->repository($repname);
    my $table_def = $rep->{table}{$table};
    my $table_column_defs = $table_def->{column};
    my $view_column_defs = $self->{column} || {};

    if (! $self->{keycolidx}) {
        $rowactions     = undef;
        $row_selectable = 0;        # can't select row(s) if no primary key
        $row_single_selectable = 0;  # can't select row    if no primary key
    }
    elsif ($rowactions && $rowactiondefs) {
        foreach $rowaction (@$rowactions) {
            if ($rowactiondefs->{$rowaction}{select} eq "single") {
                push(@single_select_actions, $rowaction);
                $row_single_selectable = 1;
            }
            elsif ($rowactiondefs->{$rowaction}{select} eq "multi") {
                push(@select_actions, $rowaction);
                $row_selectable = 1;
            }
            else {
                push(@row_actions, $rowaction);
            }
        }
    }

    # only needed for subtotals
    #my ($subtotal, $subtotal_keys, $order_by);
    #$subtotal_keys = $self->get("subtotal_keys");
    #$subtotal = (defined $subtotal_keys && ref($subtotal_keys) eq "ARRAY" && $#$subtotal_keys > -1);
    #if ($subtotal) {
    #    $order_by = $self->get("order_by") || $self->get("ordercols");   # ordercols is deprecated in favor of order_by
    #}

    my ($html, $row, $col, $elem);
    my ($td_row_attrib, $td_col_attrib, $elem_begin, $elem_end, $table_begin);

    $table_begin = "<table";
    $table_begin .= " width=\"$width\"" if (defined $width && $width ne "");
    $table_begin .= " border=\"$border\"" if (defined $border && $border ne "");
    $table_begin .= " cellspacing=\"$cellspacing\"" if (defined $cellspacing && $cellspacing ne "");
    $table_begin .= " cellpadding=\"$cellpadding\"" if (defined $cellpadding && $cellpadding ne "");
    $table_begin .= ">\n";

    $html = "<!--  -->";
    if (defined $title) {
        $title = $context->substitute($title);
        $html .= $title;
    }

    $numcols = $self->{numcols} || $#$headings + 1;

    if ($scrollable || $sortable || $filterable || $mode eq "edit") {

        $elem_begin = "";
        $elem_end = "";
        if ($font_face || $font_size || $font_color) {
            $elem_begin = "<font";
            $elem_begin .= " face=\"$font_face\""   if ($font_face);
            $elem_begin .= " size=\"" . ($font_size+1) . "\""   if ($font_size);
            $elem_begin .= " color=\"$font_color\"" if ($font_color);
            $elem_begin .= ">";
            $elem_end = "</font>";
        }

        if ($scrollable) {
            $html .= "<table border=\"0\" cellspacing=\"0\" cellpadding=\"5\"><tr><td>\n";
            $html .= "<table border=\"0\" cellspacing=\"0\" cellpadding=\"3\"><tr><td valign=\"middle\" nowrap>&nbsp;\n";
            $html .= $context->widget("$name-view",
                         class => "App::Widget::ImageButton",
                         image_script => 'app-button',
                         #volatile => 1,
                         label => 'View',
                         height => 17,
                         width => 50,
                         bevel => 2,
                     )->html();
            $html .= " ";
            if ($editable) {
                $html .= $context->widget("$name-edit",
                         class => "App::Widget::ImageButton",
                         image_script => 'app-button',
                         #volatile => 1,
                         label => 'Edit',
                         height => 17,
                         width => 50,
                         bevel => 2,
                     )->html();
                $html .= " ";
            }
            $html .= "    &nbsp;</td><td nowrap";
            $html .= " bgcolor=\"$heading_bgcolor\"" if ($heading_bgcolor);
            $html .= ">$elem_begin&nbsp;\n";
            $html .= $context->widget("$name-prev",
                         class => "App::Widget::ImageButton",
                         image_script => 'app-button',
                         #volatile => 1,
                         label => '<< Prev',
                         height => 17,
                         width => 70,
                         bevel => 2,
                     )->html();
            $html .= "\n Start Row:";
            $html .= $context->widget("$name-startrow",
                         class => "App::Widget::TextField",
                         size => 4,
                         maxlength => 12,
                     )->html();
            $html .= " Num Rows:";
            $html .= $context->widget("$name-maxrows",
                         class => "App::Widget::TextField",
                         size => 4,
                         maxlength => 12,
                     )->html();
            $html .= "\n";
            $html .= $context->widget("$name-next",
                         class => "App::Widget::ImageButton",
                         image_script => 'app-button',
                         #volatile => 1,
                         label => 'Next >>',
                         height => 17,
                         width => 70,
                         bevel => 2,

lib/App/Widget/DataTable.pm  view on Meta::CPAN

                                class => "App::Widget::ImageButton",
                                image_script => 'app-button',
                                #volatile => 1,
                                label => 'Up|Dn',
                                height => 17,
                                width => 50,
                                bevel => 2,
                                args => $col,
                            )->html();
                    $html .= "  <td>$elem</td>\n";
                }
                $html .= "</tr>\n";
            }
            if ($filterable) {
                my ($w);
                $html .= "<tr>\n";
                $html .= "  <td>&nbsp;</td>\n" if ($numbered);
                $html .= "  <td>&nbsp;</td>\n" if ($row_selectable);
                $html .= "  <td>&nbsp;</td>\n" if ($row_single_selectable);
                $html .= "  <td>&nbsp;</td>\n" if ($#row_actions > -1);
                for ($col = 0; $col < $numcols; $col++) {
                    $column = $columns->[$col];
                    #$elem = $context->widget("$name\{filter}{$column}",
                    #            class => "App::Widget::TextField",
                    #            size => 5,
                    #            maxwidth => 99,
                    #        )->html();
                    $w = $context->widget("$name\{filter}{$column}",
                                class => "App::Widget::TextField",
                                size => 5,
                                maxwidth => 99,
                         );
                    $elem = $w->html();
                    $html .= "  <td>$elem_begin$elem$elem_end</td>\n";
                }
                $html .= "</tr>\n";
            }
        }
        if ($mode eq "edit" && $column_selectable) {
            $html .= "<tr>\n";
            $html .= "  <td bgcolor=\"#ffaaaa\">&nbsp;</td>\n" if ($numbered);
            $html .= "  <td bgcolor=\"#ffaaaa\">&nbsp;</td>\n" if ($row_selectable);
            $html .= "  <td bgcolor=\"#ffaaaa\">&nbsp;</td>\n" if ($row_single_selectable);
            $html .= "  <td bgcolor=\"#ffaaaa\">&nbsp;</td>\n" if ($#row_actions > -1);
            for ($col = 0; $col < $numcols; $col++) {
                $column = $columns->[$col];
                $elem = $context->widget("$name\{column_selected}{$column}",
                            class => "App::Widget::Checkbox",
                        )->html();
                $html .= "  <td bgcolor=\"#ffaaaa\" valign=\"bottom\" align=\"center\">$elem</td>\n";
            }
            $html .= "</tr>\n";
        }
    }
    else {
        $html .= $table_begin;
    }

    $elem_begin = "";
    $elem_end = "";
    if ($font_face || $font_size || $font_color) {
        $elem_begin = "<font";
        $elem_begin .= " face=\"$font_face\""   if ($font_face);
        $elem_begin .= " size=\"$font_size\""   if ($font_size);
        $elem_begin .= " color=\"$font_color\"" if ($font_color);
        $elem_begin .= ">";
        $elem_end = "</font>";
    }

    $td_row_attrib = "";
    $td_row_attrib .= " bgcolor=\"$heading_bgcolor\"" if ($heading_bgcolor);
    $td_row_attrib .= " align=\"$heading_align\""     if ($heading_align);
    $td_row_attrib .= " valign=\"$heading_valign\""   if ($heading_valign);
    $td_row_attrib .= " nowrap" if ($heading_nowrap);

    $html .= "<tr>\n";
    $html .= "  <td bgcolor=\"$heading_bgcolor\">&nbsp;</td>\n" if ($numbered);

    if ($row_selectable) {
        if ($#select_actions > -1) {
            my (%args);
            $html .= "  <td bgcolor=\"$heading_bgcolor\" valign=\"bottom\">";
            foreach $rowaction (@select_actions) {
                %args = (
                    override => 1,
                    class => "App::Widget::ImageButton",
                    image_script => 'app-button',
                    volatile => 1,
                    height => 17,
                    width => 50,
                    bevel => 2,
                );
                $rowactiondef = $rowactiondefs->{$rowaction};
                if ($rowactiondef) {
                    foreach (keys %$rowactiondef) {
                        $args{$_} = $rowactiondef->{$_};
                    }
                }
                $html .= $context->widget("$name-${rowaction}", %args, 
                             args => "{${name}" . "{row_selected}}"
                         )->html();
                $html .= "<br>\n" if ($rowaction ne $select_actions[$#select_actions]);
            }
            $html .= "</td>\n";
        }
        else {
            $html .= "  <td bgcolor=\"#ffaaaa\">&nbsp;</td>\n";
        }
    }

    if ($row_single_selectable) {
        if ($#single_select_actions > -1) {
            my (%args);
            $html .= "  <td bgcolor=\"$heading_bgcolor\" valign=\"bottom\">";
            foreach $rowaction (@single_select_actions) {
                %args = (
                    override => 1,
                    class => "App::Widget::ImageButton",
                    image_script => 'app-button',
                    volatile => 1,
                    height => 17,
                    width => 50,
                    bevel => 2,
                );
                $rowactiondef = $rowactiondefs->{$rowaction};
                if ($rowactiondef) {
                    foreach (keys %$rowactiondef) {
                        $args{$_} = $rowactiondef->{$_};
                    }
                }
                $html .= $context->widget("$name-${rowaction}", %args, 
                             args => "{${name}" . "{row_single_selected}}"
                         )->html();
                $html .= "<br>\n" if ($rowaction ne $single_select_actions[$#select_actions]);
            }
            $html .= "</td>\n";
        }
        else {
            $html .= "  <td bgcolor=\"#ffaaaa\">&nbsp;</td>\n";
        }
    }

    $html .= "  <td bgcolor=\"$heading_bgcolor\">&nbsp;</td>\n" if ($#row_actions > -1);
    for ($col = 0; $col < $numcols; $col++) {
        $td_col_attrib = "";
        $elem = $headings->[$col];
        $elem = "&nbsp;" if (!defined $elem || $elem eq "");
        $html .= "  <td$td_row_attrib$td_col_attrib>$elem_begin$elem$elem_end</td>\n";
    }
    $html .= "</tr>\n";

    $td_row_attrib = "";
    $td_row_attrib .= " bgcolor=\"$bgcolor\"" if ($bgcolor);
    #$td_row_attrib .= " align=\"$align\"" if ($align);
    $td_row_attrib .= " valign=\"$valign\"" if ($valign);
    $td_row_attrib .= " nowrap" if ($nowrap);

    # since we are editing, we need to prepare these two arrays...
    @edit_style = ();
    @column_length = ();

    if ($mode eq "edit") {

        # prepare the style attribute arrays
        push(@edit_style, "font_family", $font_face)  if ($font_face);
        push(@edit_style, "color",      $font_color) if ($font_color);

        # This seems to cause <input> elements to take on the font size
        # currently active for text that surrounds them
        # i.e. <font size="-2"><input type="text" style="font-size: 100%;"></font>
        push(@edit_style, "font_size",   "100%")     if ($font_size);

        # border_style",
        # border_width",
        # border_color",
        # padding",
        # background_color",

        # any columns we are editing, we need to compute max width (size) for textfield
        for ($col = 0; $col < $numcols; $col++) {
            $column_length[$col] = 5;  # minimum length
            $column = "";
            if (defined $columns && defined $columns->[$col]) {
                $column = $columns->[$col];
            }
    
            if (($column ne "" && $self->{column_selected}{$column}) ||
                ($self->{row_selected} && %{$self->{row_selected}})) {
                for ($row = 0; $row <= $#$data; $row++) {
                    $elem = $data->[$row][$col];
                    if (defined $elem && length($elem) > $column_length[$col]) {
                        $column_length[$col] = length($elem);
                    }
                }
            }
        }
    }

    my ($format, $scale_factor);
    for ($row = 0; $row <= $#$data; $row++) {
        $numrow = $startrow + $row;

        $html .= "<tr>\n";

        $key = "";
        if (defined $keys && defined $keys->[$row]) {
            $key = join(",", @{$keys->[$row]});   # need to HTML-escape these!
        }

        $html .= "  <td bgcolor=\"$heading_bgcolor\" align=\"right\">$elem_begin$numrow$elem_end</td>\n" if ($numbered);

        if ($row_selectable) {
            $html .= "  <td bgcolor=\"#ffaaaa\" valign=\"middle\" align=\"center\">\n";
            $html .= $context->widget("$name\{row_selected}{$key}",
                         class => "App::Widget::Checkbox",
                     )->html();
            $html .= "  </td>\n";
        }

        if ($row_single_selectable) {
            $html .= "  <td bgcolor=\"#ffaaaa\" valign=\"middle\" align=\"center\">\n";
            $html .= $context->widget("$name\{row_single_selected}",
                         class => "App::Widget::RadioButton",
                         override => 1,
                         value => $key,
                     )->html();
            $html .= "  </td>\n";
        }

        if ($#row_actions > -1) {
            my (%args);



( run in 0.561 second using v1.01-cache-2.11-cpan-5735350b133 )