App-Widget

 view release on metacpan or  search on metacpan

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


######################################################################
## $Id: DataTable2.pm 13207 2009-08-19 12:55:27Z spadkins $
######################################################################

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

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

use strict;

=head1 NAME

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

=head1 SYNOPSIS

   use App::Widget::DataTable2;

   $name = "get_data";
   $w = App::Widget::DataTable2->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});

    if (!$self->{keycolidx}) {
        my $context = $self->{context};
        my $table   = $self->{table};
        my $rep     = $self->{repository};
        my $r       = $context->repository($rep);
        $r->_load_table_metadata($table);
        my $primary_key = $r->{table}{$table}{primary_key};
        if ($primary_key && ref($primary_key) eq "ARRAY" && $#$primary_key > -1) {
            my (@keycolidx, %colidx);
            my $columns = $self->get_columns();
            for (my $col = 0; $col <= $#$columns; $col++) {
                $colidx{$columns->[$col]} = $col;
            }
            for (my $col = 0; $col <= $#$primary_key; $col++) {
                if (defined $colidx{$primary_key->[$col]}) {
                    push(@keycolidx, $colidx{$primary_key->[$col]});
                }
            }
            $self->{keycolidx} = \@keycolidx if ($#keycolidx == $#$primary_key);
        }

lib/App/Widget/DataTable2.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::DataTable2::html(@_);
}

sub html {
    &App::sub_entry if ($App::trace);
    my $self = shift;
    $self->{context}->dbgprint("DataTable2->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->{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();
    my $compatibility  = $self->{compatibility}  || "";  # values: [HTML32]
    $startrow          = $self->{startrow}          || 1;
    $title             = $self->{title};
    $width             = $self->{width};
    $bgcolor           = $self->{bgcolor};
    $font_color        = $self->{font_color};
    $border            = $self->{border}            || 0;
    $cellspacing       = $self->{cellspacing}       || 2;
    $cellpadding       = $self->{cellpadding}       || 2;
    $align             = $self->{align}             || "";
    $valign            = $self->{valign}            || "top";
    $nowrap            = (defined $self->{nowrap}) ? $self->{nowrap} : 1;
    $font_face         = $self->{font_face}         || "verdana,geneva,arial,sans-serif";
    $font_size         = $self->{font_size}         || -2;
    $heading_bgcolor   = $self->{heading_bgcolor}   || "#cccccc";
    $heading_align     = $self->{heading_align}     || $align;
    $heading_valign    = $self->{heading_valign}    || "bottom";
    $heading_nowrap    = $self->{heading_nowrap}    || $nowrap;
    $mode              = $self->{mode}              || "view";
    $scrollable        = $self->{scrollable}        || 0;
    $sortable          = $self->{sortable}          || 0;
    $filterable        = $self->{filterable}        || 0;
    $editable          = $self->{editable}          || 0;
    my $deletable      = $self->{deletable};
    my $copyable       = $self->{copyable};
    my $addable        = $self->{addable};
    $deletable = 1     if (!defined $deletable);
    $copyable = 1      if (!defined $copyable);
    $addable = 1       if (!defined $addable);
    $numbered          = $self->{numbered}          || 1;
    $column_selectable = $self->{column_selectable} || 1;
    $row_selectable    = $self->{row_selectable}    || (($mode eq "edit") ? 1 : 0);
    $row_single_selectable = $self->{row_single_selectable} || 0;
    $keys              = $self->{keys};
    $sql               = $self->{sql};
    $rowactions        = $self->{rowactions};
    $rowactiondefs     = $self->{rowaction};

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

    if ($mode eq "edit") {
        if ($rowactions) {
            $rowactions = [ @$rowactions ];
        }
        else {
            $rowactions = [];
        }
        push(@$rowactions, "copy") if ($copyable);
        push(@$rowactions, "delete") if ($deletable);

        if ($rowactiondefs) {
            $rowactiondefs = { %$rowactiondefs };
        }
        else {
            $rowactiondefs = {};
        }
        $rowactiondefs->{copy} = {
            label => "Copy",
            select => "multi",
        };
        $rowactiondefs->{delete} = {
            label => "Delete",
            select => "multi",
        };
    }
    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
        $editable              = 0;  # can't edit if you can't select rows
    }
    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 class=\"App-DataTable-grid\"";
    $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 = "<div id=\"$name\" class=\"App-DataTable\">\n";
    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 ($compatibility eq "HTML32") {
            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-refresh",
                         class => "App::Widget::ImageButton",
                         image_script => 'App/app-button',
                         #volatile => 1,
                         label => 'Refresh',
                         height => 17,
                         width => 60,
                         bevel => 2,
                     )->html();
            $html .= " ";
            if ($editable) {
                if ($mode eq "view") {
                    $html .= $context->widget("$name-edit",
                                 class => "App::Widget::ImageButton",
                                 image_script => 'App/app-button',
                                 #volatile => 1,
                                 label => 'Edit',
                                 height => 17,
                                 width => 60,
                                 bevel => 2,
                             )->html();
                }
                else {
                    $html .= $context->widget("$name-view",
                                 class => "App::Widget::ImageButton",
                                 image_script => 'App/app-button',
                                 #volatile => 1,
                                 label => 'View',
                                 height => 17,
                                 width => 60,
                                 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/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();

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

                    #            class => "App::Widget::TextField",
                    #            size => 5,
                    #            maxlength => 99,
                    #        )->html();
                    $w = $context->widget("$name\{filter}{$column}",
                                class => "App::Widget::TextField",
                                size => 5,
                                maxlength => 99,
                         );
                    $elem = $w->html();
                    $html .= "  <td>$elem_begin$elem$elem_end</td>\n";
                }
                $html .= "</tr>\n";
            }
            if ($sortable) {
                $html .= "<tr class=\"App-DataTable-tr_sort\">\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++) {
                    $elem = $context->widget("$name-sort_$columns->[$col]",
                                class => "App::Widget::ImageButton",
                                image_script => 'App/app-button',
                                #volatile => 1,
                                label => 'Up|Dn',
                                height => 17,
                                width => 50,
                                bevel => 2,
                                args => $columns->[$col],
                            )->html();
                    $html .= "  <td>$elem</td>\n";
                }
                $html .= "</tr>\n";
            }
        }
        if ($mode eq "edit" && $column_selectable) {
            $html .= "<tr>\n";
            $html .= "  <td bgcolor=\"#ffaaaa\" class=\"App-DataTable-td_select\">&nbsp;</td>\n" if ($numbered);
            $html .= "  <td bgcolor=\"#ffaaaa\" class=\"App-DataTable-td_select\">&nbsp;</td>\n" if ($row_selectable);
            $html .= "  <td bgcolor=\"#ffaaaa\" class=\"App-DataTable-td_single_select\">&nbsp;</td>\n" if ($row_single_selectable);
            $html .= "  <td bgcolor=\"#ffaaaa\" class=\"App-DataTable-td_select\">&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\" class=\"App-DataTable-td_select\">$elem</td>\n";
            }
            $html .= "</tr>\n";
        }
    }
    else {
        $html .= $table_begin;
    }

    $elem_begin = "";
    $elem_end = "";
    if ($compatibility eq "HTML32") {
        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\" align=\"center\">";
            foreach $rowaction (@select_actions) {
                %args = (
                    override => 1,
                    class => "App::Widget::ImageButton",
                    image_script => 'App/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\" class=\"App-DataTable-td_select\">&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/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\" class=\"App-DataTable-td_single_select\">&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 .= " 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 = ();

    my ($view_widget_args, $view_widget, $view_width);

    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];
            }

            # Removed because when a row is added without a selected row
            # the inputs would be set to the minimum length
            #if (($column ne "" && $self->{column_selected}{$column}) ||
            #    ($self->{row_selected} && %{$self->{row_selected}})) { }

            if ($column ne "") {
                for ($row = 0; $row <= $#$data; $row++) {
                    $elem = $data->[$row][$col];
                    if (defined $elem && length($elem) > $column_length[$col]) {
                        $column_length[$col] = length($elem);
                    }
                }
            }
        }

        my $add_data = $self->{add_data};

        if ($add_data && $#$add_data > -1) {
            my ($errmsg, $row);

            for (my $i = 0; $i <= $#$add_data; $i++) {
                $row = $add_data->[$i];
                my ($format, $scale_factor, $edit_widget_args, $edit_widget);
                $html .= "<tr class=\"App-DataTable-tr_add\">\n";
                $html .= "  <td bgcolor=\"$heading_bgcolor\" align=\"right\">Add</td>\n" if ($numbered);
                if ($row_selectable) {
                    $errmsg = "<br />$row->{row_error}" || "&nbsp;";
                    $html .= "  <td bgcolor=\"#ffaaaa\" class=\"App-DataTable-td_select\">$errmsg</td>\n";
                }
                if ($row_single_selectable) {
                    $html .= "  <td bgcolor=\"$heading_bgcolor\">&nbsp;</td>\n";
                }
                $html .= "  <td bgcolor=\"$heading_bgcolor\">&nbsp;</td>\n" if ($#row_actions > -1);

                my $key = $i;

                for ($col = 0; $col < $numcols; $col++) {

                    if (defined $columns && defined $columns->[$col]) {
                        $column = $columns->[$col];
                        $format       = $view_column_defs->{$column}{format}       || $table_column_defs->{$column}{format};
                        $scale_factor = $view_column_defs->{$column}{scale_factor} || $table_column_defs->{$column}{scale_factor};
                        $align        = $view_column_defs->{$column}{align}        ||
                                        $table_column_defs->{$column}{align};
		        if (!$align && defined $table_column_defs->{$column}{quoted}) {



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