[svn:p5ee] r13472 - p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS

[email protected] Thu, 5 Nov 2009 09:19:31 -0800 (PST)
Newsgroups perl.cvs.p5ee
Message-ID <[email protected]>
Author: spadkins
Date: Thu Nov  5 09:19:30 2009
New Revision: 13472

Modified:
   p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS/DataTable.pm

Log:
Much more functionality and bug fixes added. Rowactions ect..

Modified: p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS/DataTable.pm
==============================================================================
--- p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS/DataTable.pm	(original)
+++ p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS/DataTable.pm	Thu Nov  5 09:19:30 2009
@@ -23,7 +23,9 @@
 
 =cut
 
+##############################
 sub _init {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self) = @_;
     $self->SUPER::_init(@_);
@@ -58,6 +60,10 @@
     my $html_url_dir      = $options->{html_url_dir} || "";
     my $ext_extension_dir = $options->{ext_extension_dir} || "/App";
     my $ext_resources_dir = $options->{ext_resources_dir} || "";
+    my $deleteable        = $self->{deleteable};
+    my $copyable          = $self->{copyable};
+    my $addable           = $self->{addable};
+    my $rowactions        = $self->{rowactions};
 
     my ($response, $js, $css);
     if ($filterable) {
@@ -87,9 +93,29 @@
             }
         }
     }
+
+    if ($deleteable || $copyable || $addable || $#$rowactions > -1) {
+        $response = $context->response() if (!$response);
+
+        $css = "${html_url_dir}${ext_resources_dir}/CheckColumn/CheckColumn.css";
+
+        if (!$response->is_included("css", $css)) {
+            $response->include("css", $css);
+        }
+
+        my @js = ( "${html_url_dir}${ext_extension_dir}/CheckColumn.js" );
+
+        foreach my $java_script (@js) {
+            if (!$response->is_included("javascript", $java_script)) {
+                $response->include("javascript", $java_script);
+            }
+        }
+    }
 }
 
+##############################
 sub repository {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self) = @_;
     my $repname = $self->{repository};
@@ -99,7 +125,9 @@
     return($rep);
 }
 
+##############################
 sub get_columns {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self) = @_;
     my ($columns);
@@ -120,7 +148,9 @@
     $columns;
 }
 
+##############################
 sub get_headings {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self) = @_;
     $self->{context}->dbgprint("DataTable->get_headings()")
@@ -150,7 +180,9 @@
     return($headings);
 }
 
+##############################
 sub get_data {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self) = @_;
     $self->{context}->dbgprint("DataTable->get_data()")
@@ -165,7 +197,9 @@
     return $data;
 }
 
+##############################
 sub load {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self) = @_;
     $self->{context}->dbgprint("DataTable->load()")
@@ -311,7 +345,9 @@
     &App::sub_exit() if ($App::trace);
 }
 
+##############################
 sub create_filter_js {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self, $col_types) = @_;
 
@@ -327,68 +363,376 @@
     $js =~ s/(.*?),\n$/$1/sg;
 
     my $filter_js = <<EOF;
-        var filters = new Ext.ux.grid.GridFilters(
-            {
-                //local:true, // tell the filter plugin to use local data.
-                filters:[
-                    $js
-                ]
-            }
-        );
+var filters = new Ext.ux.grid.GridFilters({
+        //local:true, // tell the filter plugin to use local data.
+        filters:[
+            $js
+        ]
+    });
 EOF
 
     &App::sub_exit($filter_js) if ($App::trace);
     return $filter_js;
 }
 
+##############################
+sub create_check_box_js {
+##############################
+    &App::sub_entry if ($App::trace);
+    my ($self) = @_;
+
+    my $check_box_js = <<EOF;
+var checkBoxCol = new Ext.grid.CheckColumn({
+       header:'',
+       dataIndex:'checkBoxBool',
+       menuDisabled:true,
+       width:55
+    });
+EOF
+
+    &App::sub_exit($check_box_js) if ($App::trace);
+    return $check_box_js;
+}
+
+##############################
+sub create_delete_rows_js {
+##############################
+    &App::sub_entry if ($App::trace);
+    my ($self, $table, $repository, $primary_key) = @_;
+
+    my $context        = $self->{context};
+    my $options        = $context->{options};
+    my $script_url_dir = $options->{script_url_dir}  || die "The parameter 'script_url_dir' must be set in the option file";
+    my $script_url     = "$script_url_dir/App/app-ext-repository";
+
+    my $delete_rows_js = <<EOF;
+function deleteRows(h) {
+        //console.log( Ext.util.JSON.encode( h ) );
+        Ext.Ajax.request({
+            url:     "$script_url",
+            success: function() { dataStore.reload() },
+            params:  {deleteRec: Ext.util.JSON.encode(h), table: '$table', repository: '$repository', primary_key: '$primary_key'}
+        });
+    }
+EOF
+
+    &App::sub_exit($delete_rows_js) if ($App::trace);
+    return $delete_rows_js;
+}
+
+##############################
+sub create_add_rows_js {
+##############################
+    &App::sub_entry if ($App::trace);
+    my ($self, $table, $repository) = @_;
+
+    my $context        = $self->{context};
+    my $options        = $context->{options};
+    my $script_url_dir = $options->{script_url_dir}  || die "The parameter 'script_url_dir' must be set in the option file";
+    my $script_url     = "$script_url_dir/App/app-ext-repository";
+
+    my $add_rows_js = <<EOF;
+function addRows(h) {
+        //console.log( Ext.util.JSON.encode( h ) );
+        Ext.Ajax.request({
+            url:     "$script_url",
+            success: function() { dataStore.reload() },
+            params:  { add: Ext.util.JSON.encode(h), table: '$table', repository: '$repository' }
+        });
+    }
+EOF
+
+    &App::sub_exit($add_rows_js) if ($App::trace);
+    return $add_rows_js;
+}
+
+##############################
+sub create_row_action_js {
+##############################
+    &App::sub_entry if ($App::trace);
+    my ($self) = @_;
+
+    my $row_action_js = <<EOF;
+function callRowaction(args, rowAction, name) {
+        var argStr = (args.join(","));
+        var eValue = name + '.' + rowAction + '(' + argStr + ')';
+        //console.log('arg[' + args + '] argStr[' + argStr + '] rowAction[' + rowAction + '] name[' + name + '] eValue[' + eValue + ']');
+        f = document.forms[0];
+        e = document.getElementById('app-event-aux');
+        e.value = eValue;
+        f.submit();
+        e.value = '';
+        return(false);
+    }
+EOF
+
+    &App::sub_exit($row_action_js) if ($App::trace);
+    return $row_action_js;
+}
+
+##############################
+sub create_delete_tbar_js {
+##############################
+    &App::sub_entry if ($App::trace);
+    my ($self, $primary_key) = @_;
+
+    my $delete_tbar_js = <<EOF;
+            {
+                text: 'Delete',
+                handler: function(){
+                    var primaryKey = '$primary_key';
+                    var h = {};
+                    var sm  = grid.getSelectionModel();
+                    var sel = sm.getSelections();
+                    var deleteFlg = 0;
+
+                    for ( var i = 0 ; i < sel.length ; i++ ) {
+                        if (sm.hasSelection()) {
+                            var checkBoxBool  = sel[i].get('checkBoxBool')
+                            var primaryKeyVal = sel[i].get( primaryKey );
+
+                            if (checkBoxBool == true) {
+                                grid.suspendEvents();
+                                grid.getStore().remove(sel[i]);
+                                if (primaryKeyVal != null) {
+                                    h[primaryKeyVal] = primaryKey;
+                                    deleteFlg = 1;
+                                }
+                                dataStore.modified.remove(sel[i]);
+                                grid.resumeEvents();
+                            }
+                        }
+                    }
+                    if (deleteFlg) {
+                       deleteRows(h);
+                    }
+                }
+            }
+EOF
+
+    &App::sub_exit($delete_tbar_js) if ($App::trace);
+    return $delete_tbar_js;
+}
+
+##############################
+sub create_add_tbar_js {
+##############################
+    &App::sub_entry if ($App::trace);
+    my ($self, $primary_key) = @_;
+
+    my $add_tbar_js = <<EOF;
+            {
+                text: 'Add',
+                handler: function(){
+                    var primaryKey = '$primary_key';
+                    var adds   = new Array();
+                    var sm     = grid.getSelectionModel();
+                    var sel    = sm.getSelections();
+                    var addFlg = 0;
+
+                    for ( var i = 0 ; i < sel.length ; i++ ) {
+                        if (sm.hasSelection()) {
+                            var h = {};
+                            var checkBoxBool  = sel[i].get('checkBoxBool')
+                            var primaryKeyVal = sel[i].get( primaryKey );
+                            var items         = sel[i].fields.items;
+                            if (checkBoxBool == true && primaryKeyVal == null) {
+                                grid.suspendEvents();
+                                addFlg = 1;
+                                for ( var j = 0 ; j < items.length ; j++ ) {
+                                    var fieldNm = items[j].name;
+                                    var value   = sel[i].get(fieldNm);
+                                    h[fieldNm] = value;
+                                }
+                                adds.push(h);
+                                grid.getStore().remove(sel[i]);
+                                dataStore.modified.remove(sel[i]);
+                            }
+                        }
+                    }
+                    if (addFlg) {
+                       addRows(adds);
+                       grid.resumeEvents();
+                    }
+                }
+            }
+EOF
+
+    &App::sub_exit($add_tbar_js) if ($App::trace);
+    return $add_tbar_js;
+}
+
+##############################
+sub create_copy_tbar_js {
+##############################
+    &App::sub_entry if ($App::trace);
+    my ($self, $primary_key) = @_;
+
+    my $copy_tbar_js = <<EOF;
+            {
+                text: 'Copy',
+                handler: function(){
+                    var primaryKey = '$primary_key';
+                    var sm  = grid.getSelectionModel();
+                    var sel = sm.getSelections();
+
+                    for ( var i = 0 ; i < sel.length ; i++ ) {
+                        var checked = sel[i].get('checkBoxBool');
+                        if (sm.hasSelection() && checked == true) {
+                            var h = {};
+                            var items = sel[i].fields.items;
+                            for ( var j = 0 ; j < items.length ; j++ ) {
+                                var fieldNm = items[j].name;
+                                var value   = sel[i].get(fieldNm);
+                                if (fieldNm != primaryKey) {
+                                    h[fieldNm] = value;
+                                }
+                            }
+
+                            grid.suspendEvents();
+
+                            var id     = sel[i].id;
+                            var idx    = sel[i].store.indexOfId(id);
+                            selModel.deselectRow(idx);
+                            sel[i].set('checkBoxBool', false);
+
+                            var p = new dataRec(h);
+                            grid.stopEditing();
+                            dataStore.insert(0, p);
+                            grid.startEditing(0, 0);
+
+                            dataStore.modified.remove(sel[i]);
+                            grid.resumeEvents();
+                        }
+                    }
+                }
+            }
+EOF
+
+    &App::sub_exit($copy_tbar_js) if ($App::trace);
+    return $copy_tbar_js;
+}
+
+##############################
+sub create_rowactions_tbar_js {
+##############################
+    &App::sub_entry if ($App::trace);
+    my ($self, $keycolidx, $rowactions, $rowaction, $name) = @_;
+
+    my $keycolidx_str = join(",", @$keycolidx);
+    my $rowactions_tbar_js;
+    my $single_select = 'false';
+
+    foreach my $row_action (@$rowactions) {
+        if ($rowaction->{$row_action}{select} eq "single") {
+            $single_select = 'true';
+        }
+        $rowactions_tbar_js .= <<EOF;
+            {
+                text: '$rowaction->{$row_action}{label}',
+                handler: function(){
+                    var sm   = grid.getSelectionModel();
+                    var sel  = sm.getSelections();
+                    var args      = new Array();
+                    var keyColidx = new Array();
+                    var keyColidxStr = '$keycolidx_str';
+                    keyColidx        = (keyColidxStr.split(","));
+
+                    for ( var i = 0 ; i < sel.length ; i++ ) {
+                        if (sm.hasSelection()) {
+                            var items = sel[i].fields.items;
+                            for ( var j = 0 ; j < keyColidx.length ; j++ ) {
+                                var fieldNm = items[keyColidx[j]].name;
+                                var value   = sel[i].get(fieldNm);
+                                args.push(value);
+                            }
+                        }
+                    }
+
+                    if (args.length > 0) {
+                        callRowaction(args, '$row_action', '$name');
+                    }
+                }
+            }
+EOF
+
+    }
+
+    &App::sub_exit($rowactions_tbar_js, $single_select) if ($App::trace);
+    return ($rowactions_tbar_js, $single_select);
+}
+
+##############################
 sub create_sizable_js {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self, $height, $width, $name) = @_;
 
     my $sizable_js = <<EOF;
-        var win = new Ext.Window(
-            {
-                height: $height,
-                width: $width,
-                layout: 'fit',
-                closable:false,
-                items: grid
-            }
-        );
-        
-        win.show();
-        var myDiv = Ext.get('$name');
-        win.alignTo(myDiv); 
+var win = new Ext.Window({
+        height: $height,
+        width: $width,
+        layout: 'fit',
+        closable:false,
+        items: grid
+    });
+
+    win.show();
+    var myDiv = Ext.get('$name');
+    win.alignTo(myDiv);
 EOF
 
     &App::sub_exit($sizable_js) if ($App::trace);
     return $sizable_js;
 }
 
+##############################
 sub create_edit_js {
+##############################
     &App::sub_entry if ($App::trace);
-    my ($self) = @_;
+    my ($self, $primary_key) = @_;
 
     my $edit_js = <<EOF;
-        sm: new Ext.grid.RowSelectionModel({
-            singleSelect: true
-        }),
-        listeners: {
-            afteredit: function() {
-               grid.stopEditing();
-               var changes = new Array();
-               var dirty = dataStore.getModifiedRecords();
-               var value; var col;
-               for ( var i = 0; i < dirty.length; i++ ) {
-                   var fields = dirty[i].getChanges();
-                   for(var n in fields){
-                       value = fields[n];
-                       col   = n;
-                   }
-                   changes.push(fields);
-               }
-               submitChanges(changes, col, value);
-               dataStore.commitChanges();
+listeners: {
+            afteredit: function(editEvent) {
+                if (editEvent.field == 'checkBoxBool') {
+                    if (editEvent.value == true) {
+                        if (selModel.singleSelect == true) {
+                            var dirty = dataStore.getModifiedRecords();
+                            if (dirty.length > 1) {
+                                dirty[0].set('checkBoxBool', false);
+                                dataStore.modified.remove(dirty[0]);
+                            }
+                        }
+                        selModel.selectRow(editEvent.row, 1);
+                    }
+                    else {
+                        selModel.deselectRow(editEvent.row);
+                    }
+                }
+                else {
+                    grid.suspendEvents();
+                    var primaryKey = '$primary_key';
+                    var changes = new Array();
+                    var dirty = grid.getStore().getModifiedRecords();
+                    var value; var changedField;
+                    for ( var i = 0 ; i < dirty.length ; i++ ) {
+                        var id = dirty[i].get( 'id' );
+                        var fields = dirty[i].getChanges();
+                        for(var n in fields){
+                            var h = {};
+                            value = fields[n];
+                            changedField = n;
+                            if (changedField != 'checkBoxBool') {
+                                h[changedField] = value;
+                                changes.push( h );
+                            }
+                        }
+                        dataStore.modified.remove(dirty[i]);
+                    }
+                    submitChanges(changes, changedField, value, primaryKey);
+                    grid.resumeEvents();
+                }
             }
         },
 EOF
@@ -397,7 +741,41 @@
     return $edit_js;
 }
 
+##############################
+sub create_check_box_afteredit_js {
+##############################
+    &App::sub_entry if ($App::trace);
+    my ($self) = @_;
+
+    my $check_box_afteredit_js = <<EOF;
+listeners: {
+            afteredit: function(editEvent) {
+                if (editEvent.field == 'checkBoxBool') {
+                    if (editEvent.value == true) {
+                        if (selModel.singleSelect == true) {
+                            var dirty = dataStore.getModifiedRecords();
+                            if (dirty.length > 1) {
+                                dirty[0].set('checkBoxBool', false);
+                                dataStore.modified.remove(dirty[0]);
+                            }
+                        }
+                        selModel.selectRow(editEvent.row, 1);
+                    }
+                    else {
+                        selModel.deselectRow(editEvent.row);
+                    }
+                }
+            }
+        },
+EOF
+
+    &App::sub_exit($check_box_afteredit_js) if ($App::trace);
+    return $check_box_afteredit_js;
+}
+
+##############################
 sub create_edit_submit_changes_js {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self, $table, $repository, $primary_key) = @_;
 
@@ -407,25 +785,48 @@
     my $script_url     = "$script_url_dir/App/app-ext-repository";
 
     my $edit_submit_changes_js = <<EOF;
-    function submitChanges(data, col, value) {
-        var sm      = grid.getSelectionModel();
-        var records = sm.getSelections();
-        var r       = records[0];
-        var fields  = r.fields.keys;
-        var h = {};
-        for (var i = 0; i < fields.length; i++) {
-            if (fields[i] != col) {
-                h[fields[i]] = r.json[i];
+function submitChanges(data, changedField, value, primaryKey) {
+        var sm = grid.getSelectionModel();
+        var r  = sm.getSelected();
+        var fields = r.fields.keys;
+
+        // only updating one cell at a time for now
+        var newData = new Array();
+        var dataIdx = data.length - 1;
+        newData.push(data[dataIdx]);
+
+        if (sm.hasSelection()) {
+            grid.suspendEvents();
+            var primaryKeyVal = r.get(primaryKey);
+            var id     = r.id;
+            var idx    = r.store.indexOfId(id);
+            selModel.deselectRow(idx);
+            r.set('checkBoxBool', false);
+
+            if (primaryKeyVal == null) {
+                dataStore.modified.remove(r);
+                grid.resumeEvents();
+                return;
+            }
+            else if (primaryKeyVal != null) {
+                var h = {};
+                for (var i=0; i < fields.length; i++) {
+                    if (fields[i] != changedField) {
+                        h[fields[i]] = r.get(fields[i]);
+                    }
+                }
+                //console.log(Ext.util.JSON.encode(data));
+                //console.log(Ext.util.JSON.encode(h));
+                Ext.Ajax.request({
+                    url:      "$script_url",
+                    success:  function() { dataStore.reload() },
+                    params:   { modifiedRecord: Ext.util.JSON.encode(data), record: Ext.util.JSON.encode(h), table: '$table',
+                                repository: '$repository', primary_key: '$primary_key' }
+                });
             }
+            dataStore.modified.remove(r);
+            grid.resumeEvents();
         }
-        //console.log(Ext.util.JSON.encode(data));
-        //console.log(Ext.util.JSON.encode(h));
-        Ext.Ajax.request({
-            url:        "$script_url",
-            success:    function() { dataStore.reload() },
-            params:     { modifiedRecord: Ext.util.JSON.encode(data), record: Ext.util.JSON.encode(h), table: '$table',
-                          repository: '$repository', primary_key: '$primary_key' }
-        });
     }
 EOF
 
@@ -433,8 +834,9 @@
     return $edit_submit_changes_js;
 }
 
-
+##############################
 sub html {
+##############################
     &App::sub_entry if ($App::trace);
     my ($self) = @_;
     my $name = $self->{name};
@@ -444,11 +846,15 @@
     $value = "" if (!defined $value);
     my $table = $self->{table} || "unknown";
 
-    my $scrollable = $self->{scrollable};
-    my $sortable   = $self->{sortable};
-    my $filterable = $self->{filterable};
-    my $editable   = $self->{editable};
-    my $sizable    = $self->{sizable};
+    my $scrollable    = $self->{scrollable};
+    my $sortable      = $self->{sortable};
+    my $filterable    = $self->{filterable};
+    my $editable      = $self->{editable};
+    my $sizable       = $self->{sizable};
+    my $deleteable    = $self->{deleteable};
+    my $checkbox_name = 'checkBoxCol';
+    my $copyable      = $self->{copyable};
+    my $addable       = $self->{addable};
 
     my $lock_columns = $self->{lock_columns};
 
@@ -461,14 +867,20 @@
         $primary_key = $primary_key->[0];
     }
 
+    my $keycolidx  = $self->{keycolidx};
+    my $rowactions = $self->{rowactions};
+    my $rowaction  = $self->{rowaction};
+
     my $columns = $self->get_columns();
     my $columns_list = join(",", @$columns);
     my $column_data_defs = [];
     my $column_display_defs = [];
-    my ($column_data_def, $column_display_def, $label, $column, $type, @col_types, $filter_js);
-    my ($col_width, $sizable_js, $edit_js, $edit_submit_changes_js);
+    my ($column_data_def, $column_display_def, $label, $column, $type, @col_types, $filter_js, $rowactions_tbar_js, $row_action_js, $afteredit_js);
+    my ($col_width, $sizable_js, $edit_submit_changes_js, $check_box_js, $delete_rows_js, $delete_tbar_js, $copy_tbar_js, $add_tbar_js, $add_rows_js);
     my %edit_type = ( string => 'TextField', text => 'TextField', datetime => 'TextField', integer => 'NumberField', float => 'NumberField' );
 
+    push(@$column_display_defs, $checkbox_name) if ($deleteable || $copyable || $addable || $#$rowactions > -1);
+
     for (my $i = 0; $i <= $#$columns; $i++) {
         $column = $columns->[$i];
 
@@ -505,7 +917,7 @@
         push(@col_types,            {dataIndex => $column, type => $type});
     }
 
-    my $js_column_data_defs = $self->serialize_as_javascript($column_data_defs);
+    my $js_column_data_defs    = $self->serialize_as_javascript($column_data_defs);
     my $js_column_display_defs = $self->serialize_as_javascript($column_display_defs);
 
     my $height      = $self->{height} || 490;
@@ -519,53 +931,106 @@
     }
 
     my $grid_panel_type = "Ext.grid.GridPanel";
+    my $single_select   = "false";
 
+    # filterable
     if ($filterable) {
         $filter_js = $self->create_filter_js(\@col_types);
     }
-
+    # editable
     if ($editable) {
         $grid_panel_type = "Ext.grid.EditorGridPanel";
-        $edit_js = $self->create_edit_js();
+        $afteredit_js    = $self->create_edit_js($primary_key);
         $edit_submit_changes_js = $self->create_edit_submit_changes_js($table, $repository, $primary_key);
     }
+    # deleteable
+    if ($deleteable) {
+        $check_box_js   = $self->create_check_box_js() if (!$check_box_js);
+        $delete_rows_js = $self->create_delete_rows_js($table, $repository, $primary_key);
+        $delete_tbar_js = $self->create_delete_tbar_js($primary_key);
+    }
+    # copyable
+    if ($copyable) {
+        $check_box_js = $self->create_check_box_js() if (!$check_box_js);
+        $copy_tbar_js = $self->create_copy_tbar_js($primary_key);
+    }
+    # addable
+    if ($addable) {
+        $check_box_js = $self->create_check_box_js() if (!$check_box_js);
+        $add_rows_js  = $self->create_add_rows_js($table, $repository);
+        $add_tbar_js  = $self->create_add_tbar_js($primary_key);
+    }
+    # rowactions
+    if ($#$rowactions > -1) {
+        $check_box_js  = $self->create_check_box_js() if (!$check_box_js);
+        $row_action_js = $self->create_row_action_js();
+        ($rowactions_tbar_js, $single_select) = $self->create_rowactions_tbar_js($keycolidx, $rowactions, $rowaction, $name);
+    }
 
-    my ($html);
-
-    if ($scrollable) {
-        my $context = $self->{context};
-        my $options = $context->{options};
-
-        my $order_by   = $self->{order_by};
-        $order_by = join(",", @$order_by) if (ref($order_by) eq "ARRAY");
-        my $order_by_js = $order_by ? ", order_by: '$order_by'" : "";
+    # afteredit grid listener
+    if ($check_box_js && !$afteredit_js) {
+        $afteredit_js = $self->create_check_box_afteredit_js();
+    }
 
-        my $script_url_dir = $options->{script_url_dir}  || die "The parameter 'script_url_dir' must be set in the option file";
-        my $script_url     = "$script_url_dir/App/app-ext-repository";
-        my $pagesize       = 100;
+    # tbars
+    my (@tbars, $tbar_js);
+    if ($deleteable || $copyable || $addable || $#$rowactions > -1) {
+        if ($deleteable) {
+            push(@tbars, $delete_tbar_js);
+        }
+        if ($copyable) {
+            push(@tbars, $copy_tbar_js);
+        }
+        if ($addable) {
+            push(@tbars, $add_tbar_js);
+        }
+        if ($#$rowactions > -1) {
+            push(@tbars, $rowactions_tbar_js);
+        }
 
-        my (@plugins, $plugins_js);
+        $tbar_js .= "tbar: [\n" . join(",", @tbars). "        ],";
+    }
+                               
+    # plugins
+    my (@plugins, $plugins_js);
+    if ($filterable || $deleteable || $copyable || $addable || $#$rowactions > -1) {
         if ($filterable) {
             push(@plugins, "filters");
-            $plugins_js .= "\n        plugins: " . join(",", @plugins). ",";
         }
+        if ($deleteable || $copyable || $addable || $#$rowactions > -1) {
+            push(@plugins, $checkbox_name);
+        }
+        $plugins_js .= "\n        plugins: [" . join(",", @plugins). "],";
+    }
 
-        my $render_grid_js;
-        if ($sizable) {
-            $sizable_js = $self->create_sizable_js($height, $width, $name);
-            $render_grid_js = <<EOF;
-    dataStore.load({params: {start: 0, limit: $pagesize}});
+    my ($html);
+
+    my $context = $self->{context};
+    my $options = $context->{options};
+
+    my $order_by   = $self->{order_by};
+    $order_by = join(",", @$order_by) if (ref($order_by) eq "ARRAY");
+    my $order_by_js = $order_by ? ", order_by: '$order_by'" : "";
+
+    my $script_url_dir = $options->{script_url_dir}  || die "The parameter 'script_url_dir' must be set in the option file";
+    my $script_url     = "$script_url_dir/App/app-ext-repository";
+    my $pagesize       = 100;
+
+    my $render_grid_js;
+    if ($sizable) {
+        $sizable_js = $self->create_sizable_js($height, $width, $name);
+        $render_grid_js = <<EOF;
+dataStore.load({params: {start: 0, limit: $pagesize}});
 EOF
-        }
-        else {
-            $render_grid_js = <<EOF;
-    grid.render('$name');
+    }
+    else {
+        $render_grid_js = <<EOF;
+grid.render('$name');
     dataStore.load({params: {start: 0, limit: $pagesize}});
-    grid.getSelectionModel().selectFirstRow();
 EOF
-        }
+    }
 
-        $html = <<EOF;
+    $html = <<EOF;
 <script type="text/javascript">
 Ext.onReady(function(){
 
@@ -580,6 +1045,14 @@
         baseParams: {table: '$table', repository: '$repository', columns: '$columns_list'$order_by_js}
     });
 
+    var dataRec = Ext.data.Record.create(
+        $js_column_data_defs
+    );
+
+    var selModel = new Ext.grid.RowSelectionModel({
+         singleSelect : $single_select
+    });
+
     var pagingBar = new Ext.PagingToolbar({
         pageSize: $pagesize,
         store: dataStore,
@@ -589,67 +1062,34 @@
     });
 
     $filter_js
+    $check_box_js
+    $delete_rows_js
+    $add_rows_js
+    $row_action_js
+    $edit_submit_changes_js
 
     // create the Grid
     var grid = new $grid_panel_type ({
         id: '$name-grid',
+        selModel: selModel,
         store: dataStore,$plugins_js
         columns: $js_column_display_defs,
+        $tbar_js
         stripeRows: true,
         frame:  true,
         height: $height,
         width:  $width,
         title: '$table_label',
-        $edit_js
+        $afteredit_js
         bbar: pagingBar
     });
 
     $render_grid_js
-    $edit_submit_changes_js
     $sizable_js
 });
 </script>
 <div id="$name"></div>
 EOF
-    }
-    else {
-        my $data = $self->get_data();
-        my $js_data = $self->serialize_as_javascript($data);
-
-        $html = <<EOF;
-<script type="text/javascript">
-Ext.onReady(function(){
-
-    // Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
-
-    var data = $js_data;
-
-    // create the data store
-    var dataStore = new Ext.data.SimpleStore({
-        fields: $js_column_data_defs
-    });
-    dataStore.loadData(data);
-
-    // create the Grid
-    var grid = new Ext.grid.GridPanel({
-        store: dataStore,
-        columns: $js_column_display_defs,
-        stripeRows: true,
-        frame:  true,
-        // stateful: true,
-        height: $height,
-        width:  $width,
-        title: '$table_label'
-    });
-
-    grid.render('$name');
-
-    grid.getSelectionModel().selectFirstRow();
-});
-</script>
-<div id="$name"></div>
-EOF
-    }
 
     &App::sub_exit("<html...>") if ($App::trace);
     return($html);