HTML-EditableTable

 view release on metacpan or  search on metacpan

example/example_1.cgi  view on Meta::CPAN

     },
     {
       'dbfield' => 'project_status',
       'label' => 'project status',
       'formElement' => 'popup',
       'selectionList' => ['review', 'rejected', 'approved'],
     },
     {
       'dbfield' => 'prod_date',
       'label' => 'design prod (YYYY-MM-DD)',
       'formElement' => 'calendar',
     },
     {
       'dbfield' => 'ready_for_prod_time',
       'label' => 'ready for prod date',
       'viewOnly' => 1,
     },	 
     {
       'dbfield' => 'comment',
       'label' => 'comment',
       'formElement' => 'textarea',

example/example_2.cgi  view on Meta::CPAN

     },
     {
       'dbfield' => 'project_status',
       'label' => 'project status',
       'formElement' => 'popup',
       'selectionList' => ['review', 'rejected', 'approved'],
     },
     {
       'dbfield' => 'prod_date',
       'label' => 'design prod (YYYY-MM-DD)',
       'formElement' => 'calendar',
     },
     {
       'dbfield' => 'comment',
       'label' => 'comment',
       'formElement' => 'textarea',
       'editOnly' => 1,
       'minimalEditSize' => 1,
     }
     
    );

example/example_3.cgi  view on Meta::CPAN

       'dbfield' => 'catalog_id',
       'label' => 'Catalog Id',
       'formElement' => 'textfield',
       'size' => 15,
       'uniquifierField' => 'part_id',
       'tooltip' => '2010 Catalog Number',
     },
     {
       'dbfield' => 'addition_date',
       'label' => 'Available From',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'part_name',
       'label' => 'Part Name',
       'formElement' => 'textfield',
       'size' => 20,
       'uniquifierField' => 'part_id',
     },
     {

example/example_3.cgi  view on Meta::CPAN

     {
       'dbfield' => 'reorder_class',
       'label' => 'Reorder Class',
       'formElement' => 'popup',
       'selectionList' => ['', 'A', 'B', 'C'],
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'last_order_date',
       'label' => 'Last Ordered',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },     
    );

######## CGI Controller ##########

our $t = CGI->new();
print $t->header();

print "<h3>" . "Example using EditableTable::Horizontal" . "</h3>";

example/example_4.cgi  view on Meta::CPAN

       'label' => 'Catalog Id',
       'formElement' => 'textfield',
       'size' => 15,
       'uniquifierField' => 'part_id',
       'rowspanArrayKeyForUniquification' => 'part_options',
       'rowspanArrayUniquifier' => 'option_id',
     },
     {
       'dbfield' => 'addition_date',
       'label' => 'Available From',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'part_name',
       'label' => 'Part Name',
       'formElement' => 'textfield',
       'size' => 20,
       'uniquifierField' => 'part_id',
     },
     {

example/example_4.cgi  view on Meta::CPAN

     {
       'dbfield' => 'reorder_class',
       'label' => 'Reorder Class',
       'formElement' => 'popup',
       'selectionList' => ['', 'A', 'B', 'C'],
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'last_order_date',
       'label' => 'Last Ordered',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },     
    );

######## CGI Controller ##########

our $t = CGI->new();
print $t->header();

print "<h3>" . "Example using EditableTable::Horizontal" . "</h3>";

example/example_5.cgi  view on Meta::CPAN

       'label' => 'Catalog Id',
       'formElement' => 'textfield',
       'size' => 15,
       'uniquifierField' => 'part_id',
       'rowspanArrayKeyForUniquification' => 'part_options',
       'rowspanArrayUniquifier' => 'option_id',
     },
     {
       'dbfield' => 'addition_date',
       'label' => 'Available From',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'part_name',
       'label' => 'Part Name',
       'formElement' => 'textfield',
       'size' => 20,
       'uniquifierField' => 'part_id',
     },
     {

example/example_5.cgi  view on Meta::CPAN

     {
       'dbfield' => 'reorder_class',
       'label' => 'Reorder Class',
       'formElement' => 'popup',
       'selectionList' => ['', 'A', 'B', 'C'],
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'last_order_date',
       'label' => 'Last Ordered',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },     
    );

######## CGI Controller ##########

our $t = CGI->new();
print $t->header();

print "<h3>" . "Example using EditableTable::Horizontal" . "</h3>";

example/example_6.cgi  view on Meta::CPAN

     {
       'dbfield' => 'catalog_id',
       'label' => 'Catalog Id',
       'formElement' => 'textfield',
       'size' => 15,
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'addition_date',
       'label' => 'Available From',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'part_name',
       'label' => 'Part Name',
       'formElement' => 'textfield',
       'size' => 20,
       'uniquifierField' => 'part_id',
     },
     {

example/example_6.cgi  view on Meta::CPAN

     {
       'dbfield' => 'reorder_class',
       'label' => 'Reorder Class',
       'formElement' => 'popup',
       'selectionList' => ['', 'A', 'B', 'C'],
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'last_order_date',
       'label' => 'Last Ordered',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },     
    );

######## CGI Controller ##########

our $t = CGI->new();
print $t->header();

print "<h3>" . "Example using EditableTable::Horizontal" . "</h3>";

example/example_7.cgi  view on Meta::CPAN

     {
       'dbfield' => 'catalog_id',
       'label' => 'Catalog Id',
       'formElement' => 'textfield',
       'size' => 15,
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'addition_date',
       'label' => 'Available From',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'part_name',
       'label' => 'Part Name',
       'formElement' => 'textfield',
       'size' => 20,
       'uniquifierField' => 'part_id',
     },
     {

example/example_7.cgi  view on Meta::CPAN

     {
       'dbfield' => 'reorder_class',
       'label' => 'Reorder Class',
       'formElement' => 'popup',
       'selectionList' => ['', 'A', 'B', 'C'],
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'last_order_date',
       'label' => 'Last Ordered',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },     
    );

######## CGI Controller ##########

our $t = CGI->new();
print $t->header();

print "<h3>" . "Example using EditableTable::Horizontal" . "</h3>";

example/example_8.cgi  view on Meta::CPAN

       'dbfield' => 'catalog_id',
       'label' => 'Catalog Id',
       'formElement' => 'textfield',
       'size' => 15,
       'uniquifierField' => 'part_id',
       'tooltip' => '2010 Catalog Id',
     },
     {
       'dbfield' => 'addition_date',
       'label' => 'Available From',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'part_name',
       'label' => 'Part Name',
       'formElement' => 'textfield',
       'size' => 20,
       'uniquifierField' => 'part_id',
     },
     {

example/example_8.cgi  view on Meta::CPAN

     {
       'dbfield' => 'reorder_class',
       'label' => 'Reorder Class',
       'formElement' => 'popup',
       'selectionList' => ['', 'A', 'B', 'C'],
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'last_order_date',
       'label' => 'Last Ordered',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },     
    );

my @tableFields2 = @tableFields;

######## CGI Controller ##########

our $t = CGI->new();
print $t->header();

example/example_9.cgi  view on Meta::CPAN

       'dbfield' => 'catalog_id',
       'label' => 'Catalog Id',
       'formElement' => 'textfield',
       'size' => 15,
       'uniquifierField' => 'part_id',
       'tooltip' => '2010 Catalog Id',
     },
     {
       'dbfield' => 'addition_date',
       'label' => 'Available From',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'part_name',
       'label' => 'Part Name',
       'formElement' => 'textfield',
       'size' => 20,
       'uniquifierField' => 'part_id',
     },
     {

example/example_9.cgi  view on Meta::CPAN

     {
       'dbfield' => 'reorder_class',
       'label' => 'Reorder Class',
       'formElement' => 'popup',
       'selectionList' => ['', 'A', 'B', 'C'],
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'last_order_date',
       'label' => 'Last Ordered',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },     
    );

my @tableFields2 = @tableFields;

######## CGI Controller ##########

our $t = CGI->new();
print $t->header();

lib/HTML/EditableTable.pm  view on Meta::CPAN

     {
       'dbfield' => 'catalog_id',
       'label' => 'Catalog Id',
       'formElement' => 'textfield',
       'size' => 15,
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'addition_date',
       'label' => 'Available From',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'part_name',
       'label' => 'Part Name',
       'formElement' => 'textfield',
       'size' => 20,
       'uniquifierField' => 'part_id',
     },
     {

lib/HTML/EditableTable.pm  view on Meta::CPAN

     {
       'dbfield' => 'reorder_class',
       'label' => 'Reorder Class',
       'formElement' => 'popup',
       'selectionList' => ['', 'A', 'B', 'C'],
       'uniquifierField' => 'part_id',
     },
     {
       'dbfield' => 'last_order_date',
       'label' => 'Last Ordered',
       'formElement' => 'calendar',
       'uniquifierField' => 'part_id',
     },     
    );

 ######## CGI Controller ##########

 my $t = CGI->new();
 print $t->header();

 my $context = $t->param('context') || 'view';

lib/HTML/EditableTable.pm  view on Meta::CPAN

=head1 DESCRIPTION

This module was developed to simplify the manipuation of complex tabular data in engineering and business-process web applications.  The motivation was a rapid-prototype software development flow where the requirements gathering phase goes something ...

- toggling of the table between view and edit modes with support for common html widgets

- uniquification of form element data to support processing of html form submissions of table data

- support for rowspanning

- methods to generate javascript for dynamic addition and remove of rows and commonly needed features such as 'click-to-expand' text display, calendar widget date entry, and sorting

- support for callbacks when data need to be pre-processed prior to display

For the Horizontal table, data are provided to tables in an array-of-hashes (most common case) or a hash-of-hashes.  For the Vertical table, a single hash of data produces a single column of data while a hash-of-hashes supports muliple data columns.

=head1 TABLE METHODS AND PARAMETERS

The class methods are designed along 'public' and 'private' lines.  The intended use model is indicated in the method descriptions.

=cut

lib/HTML/EditableTable.pm  view on Meta::CPAN

    # used for uniquification of elements in embedded javascript
    # since multiple tables may be in play, ensure initial value is unique
    # note each table should embed its own javascript.  Do this after 4.0 release

    $self->{'elementUid'} = $self->{'tableId'} + int(rand(1000000)); # BFBA terrible hack

    # flag to auto-display javascript if required
    $self->{javascriptDisplayed} = 0;

    # default directory for jsCaldendar when this feature is used
    $self->{calendarDir} = 'jscalendar';

    # table field parameter validation is on by default
    $self->{validateTableFieldKeys} = 1;

    # flag set when stdout is rerouted to avoid multiple acts of this
    $self->{stdoutRerouted} = 0;
    
    my $initData = shift @_;

    bless $self, $class;

lib/HTML/EditableTable.pm  view on Meta::CPAN

    if (exists $initData->{'title'}) { $self->setTitle(delete $initData->{'title'}); }
    if (exists $initData->{'tableId'}) { $self->setTableId(delete $initData->{'tableId'}); }
    if (exists $initData->{'width'}) { $self->setWidth(delete $initData->{'width'}); }
    if (exists $initData->{'style'}) { $self->setStyle(delete $initData->{'style'}); }
    if (exists $initData->{'jsAddData'}) { $self->setJsAddData(delete $initData->{'jsAddData'}); }
    if (exists $initData->{'noheader'}) { $self->setNoheader(delete $initData->{'noheader'}); }
    if (exists $initData->{'rowspannedEdit'}) { $self->setRowspannedEdit(delete $initData->{'rowspannedEdit'}); }
    if (exists $initData->{'sortOrder'}) { $self->setSortOrder(delete $initData->{'sortOrder'}); }
    if (exists $initData->{'border'}) { $self->setBorder(delete $initData->{'border'}); }
    if (exists $initData->{'suppressUndefinedFields'}) {$self->setSuppressUndefinedFields(delete $initData->{'setSuppressUndefinedFields'}); }
    if (exists $initData->{'calendarDir'}) {$self->setCalendarDir(delete $initData->{'calendarDir'}); }
    if (exists $initData->{'validateTableFieldKeys'}) {$self->setValidateTableFieldKeys(delete $initData->{'validateTableFieldKeys'}); }
    if (exists $initData->{'stringOutput'}) { $self->setStringOutput(delete $initData->{'stringOutput'}); }
    
    my @remainingInitKeys = keys %$initData;
    
    if (scalar(@remainingInitKeys)) {
	confess "one or more table parameters are not understood (@remainingInitKeys)";
    }

    # further validation

lib/HTML/EditableTable.pm  view on Meta::CPAN

# block display of undefined fields - vertical table only

sub setSuppressUndefinedFields {
    my $self = shift @_;
    my $suppressUndefinedFields = shift @_;
    $self->{'suppressUndefinedFields'} = $self->checkBool($suppressUndefinedFields);
}

=head2 getCalendarDir (public)

Returns the directory for installation of www.dynarch.com jscalendar-1.0, which is supported in the 'calendar' formElement.  Defaults to 'jscalendar'  if not set.
 
 $self->getCalendarDir();

=cut

sub getCalendarDir {
  my $self = shift @_;
  return $self->{calendarDir};
}

=head2 setCalendarDir (public)

Directory for installation of www.dynarch.com jscalendar-1.0, which is supported in the 'calendar' formElement.  Defaults to 'jscalendar'  if not set.
 
 $self->setCalendarDir('jscal_10');

=cut

sub setCalendarDir {
  my $self = shift @_;
  my $calendarDir = shift @_ || confess "missing calendar directory";
  $self->{calendarDir} = $calendarDir;
}

=head2 htmlDisplay (public)

This method renders the html to STDOUT.  If table requirements are not met, an exception will occur when this method is called.

 $table->htmlDisplay()

=cut

lib/HTML/EditableTable.pm  view on Meta::CPAN

      elsif($colSpec->{'formElement'} eq 'html5Calendar') {
	print "<input id='$id' name='$name' type=date/>";
      }
      elsif($colSpec->{'formElement'} eq 'checkbox') {

	my $checked = '';
	if ($colSpec->{'checkBehavior'} eq 'checked' ) { $checked = 'checked' }	
	print "<input type=checkbox name='$name' id='$id'  $checked/>";
      }
      
      # dynarch jscalendar-1.0 support
      
      elsif($colSpec->{'formElement'} eq 'calendar') {
	
	# script credit to www.dynarch.com
	
	my $spanText = 'Click here to add date';
	
	print "<div id=jscalsetup_$self->{tableId}>";
	print "<input type=\"hidden\" name=\"$name\" id=\"$id\"/>\n";
	print "<span style=\"background-color: \#fff; cursor: default;\"\n";
	
	print "onmouseover=\"this.style.backgroundColor='#eee';\"\n";

lib/HTML/EditableTable.pm  view on Meta::CPAN


      }
      elsif($colSpec->{'formElement'} eq 'hidden') {

	print "<td $tdFormat>";
	print hidden(-id=>$name, -name=>$name, -id=>$name, -value=>$cellValue);
	print $cellValue;
	print "</td>";
      }

      # depends on the calendar being loaded in the header

      elsif($colSpec->{'formElement'} eq 'html5Calendar') {
	print "<td $tdFormat>";
	print "<input id=\"$name\" name=\"$name\" type=date value=\"$cellValue\"/>";
	print "</td>";
      }

      # dynarch jscalendar-1.0 support

      elsif($colSpec->{'formElement'} eq 'calendar') {

	# script credit to www.dynarch.com

	my $spanText;

	if ($cellValue) {
	  $spanText = $cellValue;
	}
	else {
	  $cellValue = '';

lib/HTML/EditableTable.pm  view on Meta::CPAN



=head2 formElement (frequent)

formElement specifies the html input field that will be used when the table is in 'edit' mode.  Valid values are

=over

=item *

calendar - Implements popup calendar using www.dynarch.com jscalendar 1.0.  Requires this javascript library to be accessible.  See L</"JAVASCRIPT INTEGRATION"> for details.

=item *

checkbox - Implements checkbox html element

=item *

deleteRowButton - Combine with jsAddRow Table-level feature.  Provides button to delete a table row.

=item *

html5Calendar - Alternative to calendar.  Implements HTML5 'date' input type.  Tested with Opera, which is the only browser supporting this HTML5 input as of this writing. 

=item *

hidden - Implements hidden element type.

=item *

popup - implements CGI "poup"

=item *

lib/HTML/EditableTable.pm  view on Meta::CPAN


To provide a means to delete an added row, specify a table field with the following parameters:

 my $tableField = {
    'editOnly' => 1,
    'formElement' => 'deleteRowButton'
 }

=head2 Calendar Input Widget

Date entry is very common in the target applications of EditableTable.  A formElement of type 'calendar' is provided by impementing dynarch.com's jscalendar-1.0 widget.  The jscalendar library must be available to the webserver.  The default director...

 Calendar.setup(
   inputField     :    $name,
   ifFormat       :    "%Y-%m-%d",
   displayArea    :    "showD_$name",
   daFormat       :    "%Y-%m-%d",
   cache          :    true
 )

To provide a jscalendar input, use the formElement type 'calendar',

 my $tablField = {
  'dbfield' => 'addition_date',
  'label' => 'Available From',
  'formElement' => 'calendar',
 },

Note also that html5 provides a (much appreciated) date entry input type.  This is supported by using the formElement type 'html5calendar'.  As of this writing only Opera supported this html5 feature, however, so the jscalendar integration will be us...

=head1 SORTING

There are four techniques available to sort HTML::EditableTable::Horizontal tables and one for multi-column HTML::EditableTable::Vertical.  Each is described below along with examples.

=head2 Server-side by user

Typically used when the data for the table are presorted by SQL or in pre-processing.  In this case, set the sortHeader url, which will call the cgi script with the appropriate column field value.  The user is responsible for interpreting the cgi par...

EditableTable appends 'orderByAsc=<dbfield>' or 'orderByDesc=<dbfield>' to the url set in the call to sortHeader(), so the url must be constructed by the user in anticipation of this.  When the table is first displayed, the parameter 'orderByAsc' is ...

lib/HTML/EditableTable/Javascript.pm  view on Meta::CPAN

  'tooltip' => \&jsToolTip,
  'drillDownTruncate' => \&jsExpandText,
  'jsClearColumnOnEdit' => \&jsClearColumnOnEdit,
    );

my %tableParamJavascriptMap = (
  'jsSortHeader' => \&jsSortHeader,
    );

my %formElementTypeJavascriptMap = (
  'calendar' => \&jsCalendar10Setup,
    );

=head1 SYNOPSIS

This class provides all of the javascript functionality supported in EditableTable.  It is designed so that the javascript code used can be easily overridden with local .js files  See the documetation in L<HTML::EditableTable> for guidance on extendi...

=cut

$|=1;

lib/HTML/EditableTable/Javascript.pm  view on Meta::CPAN

    add_data_counter++;
    
    var newFieldsNode = document.getElementById('readroot_$tableId').cloneNode(true);
    newFieldsNode.id = '';
    var rowFields = newFieldsNode.childNodes;

    for (var i=0;i<rowFields.length;i++) {
      var theName = rowFields[i].name; 
      var theId = rowFields[i].id;

      // special handling for the jscalendar integration
      // using id here as div tag name attribute is not supported by FF

      if (theId == "jscalsetup_$tableId") {
	// change the name of the input and span
	
	var calFields = rowFields[i].childNodes;
 	
	// hidden input field

	calFields[0].name = calFields[0].name + '_-' + add_data_counter + '_-' + add_data_counter + '_-' + add_data_counter;
	calFields[0].id = calFields[0].name;

	// text display and trigger

	calFields[2].id = calFields[2].id + '_-' + add_data_counter + '_-' + add_data_counter + '_-' + add_data_counter;
       
	// call the calendar setup

	var calSetup = { inputField : calFields[0],
			 ifFormat : "%Y-%m-%d",
			 displayArea : calFields[2],
			 daFormat : "%Y-%m-%d",
			 cache : true    
                       };
 
	Calendar.setup(calSetup);     
      }

lib/HTML/EditableTable/Javascript.pm  view on Meta::CPAN

  }
END_JS

  $javascript .= "</script>";
  return $javascript;
}

sub jsCalendar10Setup {

  my $self = shift;
  my $calendarDir = $self->{parent}->getCalendarDir();

  my $javascript = "<style type='text/css'>\@import url($calendarDir/calendar-win2k-1.css);</style>\n";
  $javascript .=  "<script type='text/javascript' src='$calendarDir/calendar.js'></script>\n";
  $javascript .=  "<script type='text/javascript' src='$calendarDir/lang/calendar-en.js'></script>\n";
  $javascript .=  "<script type='text/javascript' src='$calendarDir/calendar-setup.js'></script>\n";
  
  return $javascript;
}

sub jsToolTip {

  my $self = shift;

  my $javascript = "<script language='javascript' type='text/javascript'>\n";
  $javascript .= <<'END_JS';



( run in 0.647 second using v1.01-cache-2.11-cpan-5dc5da66d9d )