We will start out with the cfm file.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ext JS Grid with ColdFusion</title>
<cfsetting showdebugoutput="false">
<div style="text-align:center">
<!-- Arquivos utilizados pelo jQuery lightBox plugin -->
<link rel="stylesheet" href="css/lightbox.css" type="text/css" media="screen" />
<script src="js/prototype.js" type="text/javascript"></script>
<script src="js/scriptaculous.js?load=effects,builder" type="text/javascript"></script>
<script src="js/lightbox.js" type="text/javascript"></script>
<style type="text/css">
body{ color: #333; font: 13px 'Lucida Grande', Verdana, sans-serif; }
</style>
<script type="text/javascript">
function cover_image(val){
return '<img src=images/'+val+'>';
}
</script>
<script type="text/javascript">
function renderIMG(val) {
return ('<a href="images/{val}" rel="lightbox" title="my caption" alt="{val}"> <img src="images/{val}" width="100" height="80" border="0" alt=""> </a>');}
</script>
<script>
Ext.ux.Lightbox.register('a[rel^=lightbox]');
Ext.ux.Lightbox.register('a.lb-flower', true); // true to show them as a set
</script>
<link rel="stylesheet" type="text/css" href="resources/css/ext-all.css">
<link rel="stylesheet" type="text/css" href="ux/css/RowEditor.css" />
<script src="extlightbox.js"></script>
<script src="adapter/ext/ext-base.js"></script>
<script src="js/ext-all.js"></script>
<script src="editgridItemTableMovie4.js"></script>
<script type="text/javascript" src="ux/RowEditor.js"></script>
<script type="text/javascript" src="examples/ux/CheckColumn.js"></script>
<style type="text/css">
body .x-panel {
margin-bottom:20px;
}
.icon-grid {
background-image:url(../shared/icons/fam/grid.png) !important;
}
#button-grid .x-panel-body {
border:1px solid #99bbe8;
border-top:0 none;
}
.add {
background-image:url(../shared/icons/fam/add.gif) !important;
}
.option {
background-image:url(../shared/icons/fam/plugin.gif) !important;
}
.remove {
background-image:url(../shared/icons/fam/delete.gif) !important;
}
.save {
background-image:url(../shared/icons/save.gif) !important;
}
</style>
<style type="text/css">
/*.x-btn-td {padding-left:200;}*/
/*.x-btn button {margin-left:100;}*/
.x-btn-mc {text-align:center;}
.x-btn-mc {div style=text-align:center;}
.x-btn-mc {margin-left:100; }
.ext-gen28 {margin-left:100px; position:relative;}
</style>
<style type="text/css">
.x-grid3-col{text-align:right;}
.x-grid3-col-0{text-align:right; white-space:normal !important;}
.x-grid3-col-1{text-align:left; white-space:normal !important;}
.x-grid3-col-2{text-align:left; white-space:normal !important;}
.x-grid3-col-3{text-align:left; white-space:normal !important;}
.x-grid3-col-4{text-align:right; white-space:normal !important;}
.x-grid3-header-offset {width: auto;}
.x-grid3-row td {white-space:normal !important;}
.x-grid3-hd {white-space:normal !important;}
.x-grid3-header-offset {width: auto;}
.x-grid3-hd-0-0 {white-space:normal !important;}
.x-grid3-hd-0-1 {white-space:normal !important;}
.x-grid3-hd-0-2 {white-space:normal !important;}
.x-grid3-hd-0-3 {white-space:normal !important;}
.x-grid3-td-1{white-space:normal !important;}
.x-grid3-td-2 {white-space:normal !important;}
.x-grid3-td-3 {white-space:normal !important;}
.x-toolbar-td {align: right !important;}
.x-toolbar-left {align:center;}
.x-toolbar-cell {align: center;}
.x-btn {align: center;}
.x-btn-noicon {align: center;}
.x-btn-icon-small-left {align: center;}
.ext-gen26 {align: center;}
.x-panel-bl {align: center;}
.x-btn-t1 {align: center;}
.x-btn-ml {align: center;}
.x-btn-mc {align: center;}
.x-toolbar-left {text-align:center;}
.x-btn-small {align: center;}
<!--.x-btn-small style="align:center;"}-->
.x-btn-left {align: center;}
<!---.x-grid3-td-4 {white-space:normal !important;}
.x-grid3-td-5 {white-space:normal !important;}--->
</style>
</head>
<!--<script type="application/x-javascript">
window.onload=function(){initlightbox');}
</script>-->
<body>
<div class="thumbnail">
<div id="editgrid"></div>
</div>
</body>
</html>
Here is the javascript code for the editor:
Ext.onReady(function(){
var users = Ext.data.Record.create([
{name:'ID',allowBlank:false},
{name:'COVERTHUMB',type:'string'},
{name:'TITLE',type:'string'},
{name:'DIRECTOR',type:'string'},
{name:'RELEASED',type:'date'},
{name:'RUNTIME',type:'string'},
{name:'GENRE',type:'string'},
{name:'TAGLINE',type:'string'},
{name:'PRICE',type:'float'},
{name:'AVAILABLE',type:'boolean'}
])
function cover_image(val) {
return '
';
}
//The Proxy object will specify URLs to call for different CRUD operations
var proxy = new Ext.data.HttpProxy({
method:'POST',
api:{
read: 'movies.cfc?method=getMovies',//Our URL for reading the grid data
create: 'movies.cfc?method=addMovies',//For Adding a new User (future implementation)
update: 'movies.cfc?method=editMovieRow'//When a User is updated
},
//the function writeSuccess will be called when the Store finishes a succesful write (add/edit) to the server
listeners: {
write: {
fn: writeSuccess
}
}
})
//Our JSON Writer, configuration used to updating/adding of records
var writer = new Ext.data.JsonWriter({
returnJson: true,
//We will only send the changed fields
writeAllFields: true
})
// create the Data Store
var store = new Ext.data.JsonStore({
totalProperty:'DATASET',//This is how many total records are there in the set.
root:'ROWS',//The Root of the data.
proxy:proxy,
id:'ID',
successProperty:'SUCCESS',//What return string data will be set to true/false to let Ext know that server call was succesful or not
autoSave:false,//we will use event listeners to call save manually
remoteSort:true,//We will sort server side
//Base Params are parameters passed in during every call
baseParams:{
returnFormat: 'JSON',
start: '0',
limit: '50'
},
//We define the JSON Reader for the data. We also need to set the totalProperty, root and idProperty for the dataset here.
reader: new Ext.data.JsonReader({
totalProperty:'DATASET',
root:'ROWS',
idProperty:'ID'
},users
),
//Fields read in
fields: [
'ID', 'COVERTHUMB', 'TITLE', 'DIRECTOR','RELEASED', 'RUNTIME', 'GENRE', 'TAGLINE', 'PRICE', 'AVAILABLE'
],
writer:writer,
//Any Store execeptions will be caught here
listeners: {
exception : function(proxy,type,action,options,res,rs) {
alert(type);
}
}
});
// Our Form Variable to be used for editor grid
var varForm = Ext.form;
// the check column is created using a custom plugin
var checkColumn = new Ext.grid.CheckColumn({
header: 'Available?',
dataIndex: 'AVAILABLE',
width: 55,
editor: new varForm.Checkbox({
})
});
//We setup the Grid
var cm = new Ext.grid.ColumnModel({
columns:[
new Ext.grid.RowNumberer(),//This will do numbering on the grid for us
{
header: "ID",
dataIndex:'ID',
editable: false,
width:40
},
{
header: "Cover Thumb",
dataIndex: 'COVERTHUMB',
width: 100,
hidden: false,
sortable: true,
/*renderer: imageCellRenderer,*/
renderer: cover_image,
/*renderer: renderIMG,*/
editor: new varForm.TextField({
allowBlank: false
})
},
{
header: "Title",
dataIndex: 'TITLE',
width: 150,
hidden:false,
sortable: true,
editor: new varForm.TextField({
allowBlank: false
})
}
,{
header: "Director",
dataIndex: 'DIRECTOR',
width: 100,
hidden: false,
sortable: true,
editor: new varForm.TextField({
allowBlank: false
})
},
{
header: "Released",
dataIndex: 'RELEASED',
width: 80,
type: 'date',
hidden: false,
sortable: 'true',
dateFormat: 'M d Y',
/*release_edit = new Ext.form.DateField({
format: 'm/d/Y'
}),*/
renderer: Ext.util.Format.dateRenderer('M d Y'),
editor: new varForm.DateField({
format: 'M d Y'
})
},
{
header: "Run Time",
dataIndex: 'RUNTIME',
width: 50,
hidden: false,
sortable: true,
editor: new varForm.TextField({
allowBlank: false
})
},
/*SELECT id, coverthumb, title, director, runtime, released, genre, tagline, price, available*/
{
header: "Genre",
dataIndex: 'GENRE',
width: 50,
hidden: false,
editor: new varForm.TextField
({
allowBlank: false
})
},
{
header: "Tagline",
dataIndex:'TAGLINE',
width: 250,
hidden: false,
sortable: true,
editor: new varForm.TextField({
allowBlank: false
})
},
{
header: "Price",
dataIndex: 'PRICE',
width: 50,
hidden: false,
sortable: true,
renderer: 'usMoney',
editor: new varForm.NumberField({
allowBlank: true,
allowNegative: false,
maxValue: 100000
})
}
,
checkColumn
// the plugin instance
// header: "Available",
// dataIndex: 'AVAILABLE',
// width: 100,
// /* xtype: 'checkbox',*/
// hidden: false,
// sortable: true,
// editor: new varForm.Checkbox({
// })
]
})
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
rowselect: function(smObj, rowIndex, record) {
selRecordStore = record;
}
}
})
// var rowEditor = new Ext.ux.grid.RowEditor({
// saveText: 'Update',
// listeners: {
// afteredit: syncStore
// }
// });
// create the editor grid
var grid = new Ext.grid.EditorGridPanel({
width:1100,
height:500,
title:'Browse through the Items in Donnas Shop',
store: store,
trackMouseOver:true,
disableSelection:false,
loadMask: true,
stripeRows: true,
collapsible: true,
columnLines: true,
iconcls:'icon-grid',
cm:cm,//Our column model
frame:true,//Make it more nicer looking (?)
clicksToEdit: 1,//One click on row data will bring on edit box
renderTo:'editgrid',
region: 'center',
// inline buttons
buttons:[{text:'Save'},{xtype:'tbfill'},{text:'Cancel'},{xtype:'tbfill'}],
buttonAlign:'center'
/*
,
plugins: [new Ext.ux.grid.RowEditor()
]
*/
,
// paging bar on the bottom
bbar: new Ext.PagingToolbar({
pageSize: 50,
store: store,
displayInfo: true,
displayMsg: 'Displaying Records {0} - {1} of {2}',
emptyMsg: "No Records to display",
items:[
'-', {
pressed: true,
enableToggle:true,
text: 'Show Preview',
iconCls: 'icons/user_suit.gif'
//cls: 'x-tbar-loading',
},'-', {
pressed: true,
enableToggle:true,
text: 'Show Preview',
icon: 'icons/user_female.gif'
//cls: 'x-tbar-loading'
}]
}) ,
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
rowselect: function(smObj, rowIndex, record) {
selRecordStore = record;
}
}
}),
// inline toolbars
tbar: new Ext.Toolbar({
items : [
{
xtype:'tbtext',
text:'Welcome. Click here to edit .',
itemId:'tbartext',
id:'tbartext'
},
{
text:'Add A New Store Item',
tooltip:'Add a new row',
icon:'icons/fam/add.gif',
handler: function() {
Ext.Ajax.request({
url: 'movies.cfc?method=addMovie',
params: {
action: 'create',
title: 'New Movie'
},
success: function(resp,opt) {
var INSERT_ID = Ext.util.JSON.decode(
resp.responseText
).INSERT_ID;
grid.getStore().insert(0,
new users({
/*var user1 = new users({*/
ID: INSERT_ID,
COVERTHUMB: 'blankmovie.jpg',
TITLE: 'Great Movie',
DIRECTOR: 'Movie Director',
RUNTIME: 2,
RELEASED: '03/15/2011',
GENRE: 1,
TAGLINE: 'Great Movie',
PRICE: 22.99,
AVAILABLE: 1
}, INSERT_ID)
);
grid.startEditing(0,0);
},
failure: function(resp,opt) {
Ext.Msg.alert('Error','Unable to add movie');
}
});
store.insert(0, Users);
grid.getView().refresh();
grid.getSelectionModel().selectRow(0);
}
}, '-', {
text:'Options',
tooltip:'Blah blah blah blaht',
icon:'icons/fam/connect.gif'
},'-',{
xtype:'tbbutton',
text:'Remove Movie',
tooltip:'Remove the selected movie',
icon:'icons/fam/delete.gif',
handler: function() {
var sm = grid.getSelectionModel(),
sel = sm.getSelected();
if (sm.hasSelection()){
Ext.Msg.show({
/*Download from Wow! eBook
Editor Grids
[ 136 ]*/
title: 'Remove Movie',
buttons: Ext.MessageBox.YESNOCANCEL,
msg: 'Remove '+sel.data.TITLE+'?',
fn: function(btn){
if (btn == 'yes'){
Ext.Ajax.request({
url: 'movies.cfc?method=removeMovies',
params: {
method: 'removeMovies',
action: 'destroy',
/*id: e.record.ID*/
/*id: e.data.ID*/
id: sel.data.ID
},
success: function(resp,opt) {
grid.getStore().remove(sel);
},
failure: function(resp,opt) {
Ext.Msg.alert('Error',
'Unable to delete movie');
}
});
}
}
});
};
}
/*}*/
/* // Place a reference in the GridPanel
ref: '../removeButton',
disabled: true*/
}
]
}
),
listeners: {
afteredit: { //This listener event function will be called when user finishes editing data box and tabs/enters/clicks out.
fn: editStore
}
}
});
function editStore(e)
{
//Call our store's save event that will fire things off'
this.store.save();
}
function onAdd(e)
{
var u = new this.store.recordType({
ItemID: '',
ItemIdentifier: 'VP1',
ItemDescription: 'My Description',
ItemTitle: 'President'
});
this.stopEditing();
this.store.insert(0, u);
this.startEditing(0, 1);
}
function syncStore(rowEditor, changes, r, rowIndex) {
store.save();
}
/*write(dataproxy,action,data,response,record,options)*/
function writeSuccess(store, action, data, response, rs, options )
/* function writeSuccess(store, action, result, res, rs, resp, opt)*/
{
//Get Toolbar Object
var tbar = grid.getTopToolbar();
//Remove current text
tbar.remove("tbartext");
tbar.addText({
xtype:'tbtext',
text:'Success !! ' + action,
itemId:'tbartext'
}
);
//Redo layout to render new toolbar text
tbar.doLayout();
}
//Default Sort set for the grid load call
store.setDefaultSort('ID','ASC');
// trigger the data store load
store.load();
});
And finally here is the CFC. Take a look at the method to editMovieRow as it is designed to handle one row or an array. If you included all the javascript files mentioned in the html, this should all work for you. Oh, make sure you are running Ext JS 3.2. If you do not have those files you can get them from here: https://code.google.com/p/extjs-public/source/browse/tags/extjs-3.2.1?r=117#extjs-3.2.1
SELECT ID as id, coverthumb, title, director, runtime, released, genre, tagline, price, available FROM movies SELECT ID, COVERTHUMB, TITLE, DIRECTOR, URL, RUNTIME, RELEASED, PRICE, AVAILABLE FILMED_IN, GENRE, TAGLINE, PRICE, AVAILABLE, DESCRIPTION FROM movies Order by GENRE // Define the local scope. var LOCAL = StructNew(); // Get the column names as an array. LOCAL.Columns = ListToArray( ARGUMENTS.Data.ColumnList ); // Create a structure that will hold the Store. LOCAL.Store.columns = LOCAL.Columns; // Create a second array for the data LOCAL.DataArray = ArrayNew(1); // Loop over the query. for (LOCAL.RowIndex = 1 ; LOCAL.RowIndex LTE ARGUMENTS.Data.RecordCount ; LOCAL.RowIndex = (LOCAL.RowIndex + 1)){ // Create an array for this row LOCAL.Row = ArrayNew(1); // Loop over the columns in this row. for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE ArrayLen( LOCAL.Columns ) ; LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){ // Get a reference to the query column. LOCAL.ColumnName = LOCAL.Columns[ LOCAL.ColumnIndex ]; // Store the query cell value into the array by key. LOCAL.Row[ LOCAL.ColumnIndex ] = ARGUMENTS.Data[ LOCAL.ColumnName ][ LOCAL.RowIndex ]; } // Add the row array to the data array. ArrayAppend( LOCAL.DataArray, LOCAL.Row ); } // Add the Data array to the query array LOCAL.Store.data = LOCAL.DataArray ; // Return the store return( LOCAL.Store ); arrRecords = arrayNew(1); if(arguments.start==0) { counter = 1; } else { counter = arguments.start; } for(i=1;i<=arguments.limit;i++) { strResults = structNew(); for(x=1;x<=listLen(clist);x++) { strResults[ucase(listGetAt(clist,x))] = query[listGetAt(clist,x)][counter]; } arrRecords[i] = strResults; counter = counter+1; } return arrRecords; UPDATE movies SET #PreserveSingleQuotes(strUpdQuery)# WHERE id = #Arguments.id# UPDATE movies SET Price = #Arguments.value# WHERE id = #Arguments.id# UPDATE movies SET TITLE = '#stcData[x].TITLE#', DIRECTOR = '#stcData[x].DIRECTOR#', TAGLINE = '#stcData[x].TAGLINE#', GENRE = 1, GENRE = '#stcData[x].GENRE#', RELEASED = '11/15/2010', RELEASED = '#DateFormat(left(stcData[x].RELEASED,10),"mm/dd/yyyy")#', WHERE ID = #stcData[x].ID# RUNTIME = 2 RUNTIME = #stcData[x].RUNTIME# UPDATE movies SET COVERTHUMB = '#stcData.COVERTHUMB#', TITLE = '#stcData.TITLE#', DIRECTOR = '#stcData.DIRECTOR#', GENRE = #stcData.GENRE#, GENRE = 1, GENRE = 1, TAGLINE = '#stcData.TAGLINE#', WHERE ID = #stcData.id# RELEASED = '10/27/2012' RELEASED = '#stcData.RELEASED#' Delete from movies WHERE id = #Arguments.id# Insert into Movies ( TITLE, DIRECTOR, RELEASED, GENRE, TAGLINE, COVERTHUMB, AVAILABLE, RUNTIME, PRICE ) Values ( 'New TITLE', 'DIRECTOR', 03/01/2011, '1', 'Great Movie', 'blankmovie.jpg', 1, 1, 24.99 ) Select max(ID) as myID from movies where TITLE = 'New TITLE'
Enjoy!
No comments:
Post a Comment