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> \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 .= " </td><td nowrap";
$html .= " bgcolor=\"$heading_bgcolor\"" if ($heading_bgcolor);
$html .= ">$elem_begin \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> </td>\n" if ($numbered);
$html .= " <td> </td>\n" if ($row_selectable);
$html .= " <td> </td>\n" if ($row_single_selectable);
$html .= " <td> </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\"> </td>\n" if ($numbered);
$html .= " <td bgcolor=\"#ffaaaa\" class=\"App-DataTable-td_select\"> </td>\n" if ($row_selectable);
$html .= " <td bgcolor=\"#ffaaaa\" class=\"App-DataTable-td_single_select\"> </td>\n" if ($row_single_selectable);
$html .= " <td bgcolor=\"#ffaaaa\" class=\"App-DataTable-td_select\"> </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\"> </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\"> </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\"> </td>\n";
}
}
$html .= " <td bgcolor=\"$heading_bgcolor\"> </td>\n" if ($#row_actions > -1);
for ($col = 0; $col < $numcols; $col++) {
$td_col_attrib = "";
$elem = $headings->[$col];
$elem = " " 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}" || " ";
$html .= " <td bgcolor=\"#ffaaaa\" class=\"App-DataTable-td_select\">$errmsg</td>\n";
}
if ($row_single_selectable) {
$html .= " <td bgcolor=\"$heading_bgcolor\"> </td>\n";
}
$html .= " <td bgcolor=\"$heading_bgcolor\"> </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 )