added: DataTable asset
This commit is contained in:
parent
828930d193
commit
3e1f66a0e7
9 changed files with 1638 additions and 0 deletions
407
lib/WebGUI/Form/DataTable.pm
Normal file
407
lib/WebGUI/Form/DataTable.pm
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
package WebGUI::Form::DataTable;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2008 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Form::Control';
|
||||
use WebGUI::International;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Form::DataTable
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Create an editable table. Users can add columns and rows to the table.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
This is a subclass of WebGUI::Form::Control.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
The following methods are specifically available from this class. Check the superclass for additional methods.
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( [ additionalTerms ] )
|
||||
|
||||
See the super class for additional details.
|
||||
|
||||
=head3 additionalTerms
|
||||
|
||||
The following additional parameters have been added via this sub class.
|
||||
|
||||
=head4 ajaxDataUrl
|
||||
|
||||
This is the URL to get the data from, AJAX-style.
|
||||
|
||||
=head4 ajaxDataFunc
|
||||
|
||||
This is the ?func= to get the data from.
|
||||
|
||||
=head4 ajaxSaveUrl
|
||||
|
||||
This is the URL to send AJAX requests to. If this exists, will send
|
||||
updates to the table asyncronously.
|
||||
|
||||
=head4 ajaxSaveFunc
|
||||
|
||||
This is the ?func= to send AJAX requests to.
|
||||
|
||||
=head4 showEdit
|
||||
|
||||
If true, will enable the table for editing. This is only necessary when
|
||||
displaying the table with getValueAsHtml().
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift || [];
|
||||
|
||||
push @{$definition}, {
|
||||
showEdit => {
|
||||
defaultValue => 0,
|
||||
},
|
||||
ajaxDataUrl => {
|
||||
defaultValue => undef,
|
||||
},
|
||||
ajaxDataFunc => {
|
||||
defaultValue => "view",
|
||||
},
|
||||
ajaxSaveUrl => {
|
||||
defaultValue => undef,
|
||||
},
|
||||
ajaxSaveFunc => {
|
||||
defaultValue => "view",
|
||||
},
|
||||
};
|
||||
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getDataTableHtml ( )
|
||||
|
||||
Render the DataTable
|
||||
|
||||
=cut
|
||||
|
||||
sub getDataTableHtml {
|
||||
my $self = shift;
|
||||
|
||||
$self->prepare unless $self->{_prepared};
|
||||
|
||||
my $data = JSON->new->decode( $self->getOriginalValue );
|
||||
my $id = $self->get( 'id' );
|
||||
|
||||
# Get the HTML for the table
|
||||
my $html = $self->getTableHtml( $data );
|
||||
|
||||
### Prepare the columns data
|
||||
my %parsers = (
|
||||
date => "YAHOO.util.DataSource.parseDate",
|
||||
number => "YAHOO.util.DataSource.parseNumber",
|
||||
);
|
||||
|
||||
my %editors = (
|
||||
date => "date",
|
||||
textbox => "textbox",
|
||||
);
|
||||
|
||||
my @columnsJson = ();
|
||||
for my $column ( @{ $data->{ columns } } ) {
|
||||
# Not using a datastructure and JSON.pm because of function references for "parser"
|
||||
my $columnDef = '{'
|
||||
. qq{"key" : "$column->{ key }", }
|
||||
. qq{"abbr" : "$column->{ key }", }
|
||||
. qq{"formatter" : "$column->{ formatter }", }
|
||||
. qq{"resizable" : 1, }
|
||||
. qq{"sortable" : 1}
|
||||
;
|
||||
|
||||
# Automatically determine the parser to use
|
||||
if ( $parsers{ $column->{ formatter } } ) {
|
||||
$columnDef .= qq{, "parser" : $parsers{ $column->{ formatter } }};
|
||||
};
|
||||
|
||||
# If we can edit
|
||||
if ( $self->get( 'showEdit' ) ) {
|
||||
# Set the editor
|
||||
my $editor = $editors{ $column->{ formatter } }
|
||||
|| $editors{ "textbox" }
|
||||
;
|
||||
$columnDef .= qq{, "editor" : "$editor"};
|
||||
}
|
||||
$columnDef .= '}';
|
||||
|
||||
push @columnsJson, $columnDef;
|
||||
}
|
||||
my $columnsJson = "[" . join( ",", @columnsJson ) . "]";
|
||||
|
||||
### Prepare any options
|
||||
my $options = {
|
||||
"showEdit" => $self->get( 'showEdit' ),
|
||||
"inputName" => $self->get( 'name' ),
|
||||
"ajaxDataUrl" => $self->get( 'ajaxDataUrl' ),
|
||||
"ajaxDataFunc" => $self->get( 'ajaxDataFunc' ),
|
||||
"ajaxSaveUrl" => $self->get( 'ajaxSaveUrl' ),
|
||||
"ajaxSaveFunc" => $self->get( 'ajaxSaveFunc' ),
|
||||
};
|
||||
my $optionsJson = JSON->new->encode( $options );
|
||||
|
||||
# Progressively enhance the bejesus out of it
|
||||
$html .= <<"ENDJS";
|
||||
<script type="text/javascript">
|
||||
var myDataTable = WebGUI.Form.DataTable( "$id-container", $columnsJson, $optionsJson );
|
||||
</script>
|
||||
ENDJS
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getDefaultValue ( )
|
||||
|
||||
Get the default value. If none exists, return at least an appropriate
|
||||
data structure.
|
||||
|
||||
=cut
|
||||
|
||||
sub getDefaultValue {
|
||||
my $self = shift;
|
||||
my $value = $self->SUPER::getDefaultValue( @_ );
|
||||
|
||||
if ( !$value ) {
|
||||
$value = JSON->new->encode(
|
||||
{
|
||||
columns => [
|
||||
{
|
||||
key => "New Column",
|
||||
formatter => "text",
|
||||
},
|
||||
],
|
||||
rows => [
|
||||
{
|
||||
"New Column" => "Value",
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getName ( session )
|
||||
|
||||
Returns the name of the form control.
|
||||
|
||||
=cut
|
||||
|
||||
sub getName {
|
||||
my ($class, $session) = @_;
|
||||
return WebGUI::International->new($session, "Form_DataTable")->get("topicName");
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getOriginalValue ( )
|
||||
|
||||
Get the original value, or the default value.
|
||||
|
||||
=cut
|
||||
|
||||
sub getOriginalValue {
|
||||
my $self = shift;
|
||||
my $value = $self->SUPER::getOriginalValue( @_ );
|
||||
|
||||
if ( !$value ) {
|
||||
$value = $self->getDefaultValue;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getValue ( [ value ] )
|
||||
|
||||
Return the data for the table in a serialized JSON object with the following
|
||||
structure.
|
||||
|
||||
$VAR1 = {
|
||||
columns => [
|
||||
{
|
||||
key => column name,
|
||||
formatter => "", one of "button", "checkbox", "currency", "date", "dropdown",
|
||||
"email", "link", "number", "radio", "text", "textarea", "textbox"
|
||||
// FUTURE ENHANCEMENTS
|
||||
editor => "", one of "text", "date", "dropdown", "radio", "check"
|
||||
editorOptions => [ ... ], needed for "dropdown", "radio", "check"
|
||||
resizable => 1,
|
||||
sortable => 1,
|
||||
},
|
||||
],
|
||||
rows => [
|
||||
{
|
||||
column name => value,
|
||||
column name => value,
|
||||
...
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub getValue {
|
||||
my $self = shift;
|
||||
my $value = $self->SUPER::getValue(@_);
|
||||
|
||||
# If passing in a data structure, encode to JSON
|
||||
if ( ref $value eq "HASH" ) {
|
||||
$value = JSON->new->encode( $value );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getValueAsHtml ( )
|
||||
|
||||
Get the value as HTML. Render the datatable in a non-editable form.
|
||||
|
||||
=cut
|
||||
|
||||
sub getValueAsHtml {
|
||||
my $self = shift;
|
||||
return $self->getDataTableHtml;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getTableHtml ( [data] )
|
||||
|
||||
Get the HTML to render the table. C<data> is the data structure with
|
||||
columns and rows to render. Defaults to C<getValue>.
|
||||
|
||||
=cut
|
||||
|
||||
sub getTableHtml {
|
||||
my $self = shift;
|
||||
my $data = shift;
|
||||
|
||||
my $html = '<div id="' . $self->get('id') . '-container" class="yui-skin-sam">';
|
||||
|
||||
# Only insert the table if we're not getting AJAX Data
|
||||
if ( !$self->get( "ajaxDataUrl" ) ) {
|
||||
$html .= '<table id="' . $self->get('id') . '-container-table"><thead><tr>';
|
||||
|
||||
for my $column ( @{ $data->{ columns } } ) {
|
||||
$html .= '<th>' . $column->{ key } . '</th>';
|
||||
}
|
||||
|
||||
# TODO: Add table footer
|
||||
$html .= '</tr></thead><tbody>';
|
||||
|
||||
for my $row ( @{ $data->{ rows } } ) {
|
||||
$html .= '<tr>';
|
||||
|
||||
for my $column ( @{ $data->{ columns } } ) {
|
||||
$html .= '<td>' . $row->{ $column->{ key } } . '</td>';
|
||||
}
|
||||
|
||||
$html .= '</tr>';
|
||||
}
|
||||
|
||||
$html .= '</tbody></table>';
|
||||
}
|
||||
|
||||
$html .= '</div>';
|
||||
|
||||
# Add hidden form element to hold JSON
|
||||
if ( $self->get( 'showEdit' ) ) {
|
||||
$html .= '<input type="hidden" name="' . $self->get( 'name' ) . '" />';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 prepare ( )
|
||||
|
||||
Load all the script and css files we need. Call this in prepareView() if needed.
|
||||
Otherwise, is called automatically.
|
||||
|
||||
=cut
|
||||
|
||||
sub prepare {
|
||||
my $self = shift;
|
||||
|
||||
# Source in the scripts
|
||||
my $style = $self->session->style;
|
||||
my $url = $self->session->url;
|
||||
$style->setLink( $url->extras( 'yui/build/datatable/assets/skins/sam/datatable.css' ), { rel => "stylesheet", type => "text/css" } );
|
||||
$style->setScript( $url->extras( 'yui/build/yahoo-dom-event/yahoo-dom-event.js' ) );
|
||||
$style->setScript( $url->extras( 'yui/build/element/element-beta.js' ) );
|
||||
$style->setScript( $url->extras( 'yui/build/dragdrop/dragdrop-min.js' ) );
|
||||
$style->setScript( $url->extras( 'yui/build/connection/connection-min.js' ) );
|
||||
$style->setScript( $url->extras( 'yui/build/json/json-min.js' ) );
|
||||
|
||||
# Prepare the editors
|
||||
if ( $self->get( 'showEdit' ) ) {
|
||||
$style->setLink( $url->extras( 'yui/build/button/assets/skins/sam/button.css', { rel => "stylesheet", type => "text/css" } ) );
|
||||
$style->setLink( $url->extras( 'yui/build/calendar/assets/skins/sam/calendar.css', { rel => "stylesheet", type => "text/css" } ) );
|
||||
$style->setLink( $url->extras( 'yui/build/container/assets/skins/sam/container.css' ), { rel => "stylesheet", type => "text/css" } );
|
||||
$style->setScript( $url->extras( 'yui/build/container/container-min.js' ) );
|
||||
$style->setScript( $url->extras( 'yui/build/button/button-min.js' ) );
|
||||
$style->setScript( $url->extras( 'yui/build/calendar/calendar-min.js' ) );
|
||||
}
|
||||
|
||||
$style->setScript( $url->extras( 'yui-webgui/build/i18n/i18n.js' ) );
|
||||
$style->setScript( $url->extras( 'yui/build/datasource/datasource.js' ) );
|
||||
$style->setScript( $url->extras( 'yui/build/datatable/datatable.js' ) );
|
||||
$style->setScript( $url->extras( 'yui-webgui/build/form/datatable.js' ) );
|
||||
|
||||
$self->{_prepared} = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 toHtml ( )
|
||||
|
||||
Render the DataTable in an editable format.
|
||||
|
||||
=cut
|
||||
|
||||
sub toHtml {
|
||||
my $self = shift;
|
||||
$self->set( 'showEdit', 1 );
|
||||
return $self->getDataTableHtml;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue