lironla
12 Apr 2012, 6:43 AM
I've followed the forum and copied the plugin code :
http://www.sencha.com/forum/showthread.php?21913-SOLVED-Grid-Drag-and-Drop-reorder-rows/page8
Ext.namespace('Ext.ux.dd');
Ext.ux.dd.GridDragDropRowOrder = Ext.extend(Ext.util.Observable,
{
copy: false,
scrollable: false,
constructor : function(config)
{
if (config)
Ext.apply(this, config);
this.addEvents(
{
beforerowmove: true,
afterrowmove: true,
beforerowcopy: true,
afterrowcopy: true
});
Ext.ux.dd.GridDragDropRowOrder.superclass.constructor.call(this);
},
init : function (grid)
{
this.grid = grid;
grid.enableDragDrop = true;
grid.on({
render: { fn: this.onGridRender, scope: this, single: true }
});
},
onGridRender : function (grid)
{
var self = this;
this.target = new Ext.dd.DropTarget(grid.getEl(),
{
ddGroup: grid.ddGroup || 'GridDD',
grid: grid,
gridDropTarget: this,
notifyDrop: function(dd, e, data)
{
// Remove drag lines. The 'if' condition prevents null error when drop occurs without dragging out of the selection area
if (this.currentRowEl)
{
this.currentRowEl.removeClass('grid-row-insert-below');
this.currentRowEl.removeClass('grid-row-insert-above');
}
// determine the row
var t = Ext.lib.Event.getTarget(e);
var rindex = this.grid.getView().findRowIndex(t);
if (rindex === false || rindex == data.rowIndex)
{
return false;
}
// fire the before move/copy event
if (this.gridDropTarget.fireEvent(self.copy ? 'beforerowcopy' : 'beforerowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections, 123) === false)
{
return false;
}
// update the store
var ds = this.grid.getStore();
// Changes for multiselction by Spirit
var selections = new Array();
var keys = ds.data.keys;
for (var key in keys)
{
for (var i = 0; i < data.selections.length; i++)
{
if (keys[key] == data.selections[i].id)
{
// Exit to prevent drop of selected records on itself.
if (rindex == key)
{
return false;
}
selections.push(data.selections[i]);
}
}
}
// fix rowindex based on before/after move
if (rindex > data.rowIndex && this.rowPosition < 0)
{
rindex--;
}
if (rindex < data.rowIndex && this.rowPosition > 0)
{
rindex++;
}
// fix rowindex for multiselection
if (rindex > data.rowIndex && data.selections.length > 1)
{
rindex = rindex - (data.selections.length - 1);
}
// we tried to move this node before the next sibling, we stay in place
if (rindex == data.rowIndex)
{
return false;
}
// fire the before move/copy event
/* dupe - does it belong here or above???
if (this.gridDropTarget.fireEvent(self.copy ? 'beforerowcopy' : 'beforerowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections, 123) === false)
{
return false;
}
*/
if (!self.copy)
{
for (var i = 0; i < data.selections.length; i++)
{
ds.remove(ds.getById(data.selections[i].id));
}
}
for (var i = selections.length - 1; i >= 0; i--)
{
var insertIndex = rindex;
ds.insert(insertIndex, selections[i]);
}
// re-select the row(s)
var sm = this.grid.getSelectionModel();
if (sm)
{
sm.selectRecords(data.selections);
}
// fire the after move/copy event
this.gridDropTarget.fireEvent(self.copy ? 'afterrowcopy' : 'afterrowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections);
return true;
},
notifyOver: function(dd, e, data)
{
var t = Ext.lib.Event.getTarget(e);
var rindex = this.grid.getView().findRowIndex(t);
// Similar to the code in notifyDrop. Filters for selected rows and quits function if any one row matches the current selected row.
var ds = this.grid.getStore();
var keys = ds.data.keys;
for (var key in keys)
{
for (var i = 0; i < data.selections.length; i++)
{
if (keys[key] == data.selections[i].id)
{
if (rindex == key)
{
if (this.currentRowEl)
{
this.currentRowEl.removeClass('grid-row-insert-below');
this.currentRowEl.removeClass('grid-row-insert-above');
}
return this.dropNotAllowed;
}
}
}
}
// If on first row, remove upper line. Prevents negative index error as a result of rindex going negative.
if (rindex < 0 || rindex === false)
{
this.currentRowEl.removeClass('grid-row-insert-above');
return this.dropNotAllowed;
}
try
{
var currentRow = this.grid.getView().getRow(rindex);
// Find position of row relative to page (adjusting for grid's scroll position)
var resolvedRow = new Ext.Element(currentRow).getY() - this.grid.getView().scroller.dom.scrollTop;
var rowHeight = currentRow.offsetHeight;
// Cursor relative to a row. -ve value implies cursor is above the row's middle and +ve value implues cursor is below the row's middle.
this.rowPosition = e.getPageY() - resolvedRow - (rowHeight/2);
// Clear drag line.
if (this.currentRowEl)
{
this.currentRowEl.removeClass('grid-row-insert-below');
this.currentRowEl.removeClass('grid-row-insert-above');
}
if (this.rowPosition > 0)
{
// If the pointer is on the bottom half of the row.
this.currentRowEl = new Ext.Element(currentRow);
this.currentRowEl.addClass('grid-row-insert-below');
}
else
{
// If the pointer is on the top half of the row.
if (rindex - 1 >= 0)
{
var previousRow = this.grid.getView().getRow(rindex - 1);
this.currentRowEl = new Ext.Element(previousRow);
this.currentRowEl.addClass('grid-row-insert-below');
}
else
{
// If the pointer is on the top half of the first row.
this.currentRowEl.addClass('grid-row-insert-above');
}
}
}
catch (err)
{
console.warn(err);
rindex = false;
}
return (rindex === false)? this.dropNotAllowed : this.dropAllowed;
},
notifyOut: function(dd, e, data)
{
// Remove drag lines when pointer leaves the gridView.
if (this.currentRowEl)
{
this.currentRowEl.removeClass('grid-row-insert-above');
this.currentRowEl.removeClass('grid-row-insert-below');
}
}
});
if (this.targetCfg)
{
Ext.apply(this.target, this.targetCfg);
}
if (this.scrollable)
{
Ext.dd.ScrollManager.register(grid.getView().getEditorParent());
grid.on({
beforedestroy: this.onBeforeDestroy,
scope: this,
single: true
});
}
},
getTarget: function()
{
return this.target;
},
getGrid: function()
{
return this.grid;
},
getCopy: function()
{
return this.copy ? true : false;
},
setCopy: function(b)
{
this.copy = b ? true : false;
},
onBeforeDestroy : function (grid)
{
// if we previously registered with the scroll manager, unregister
// it (if we don't it will lead to problems in IE)
Ext.dd.ScrollManager.unregister(grid.getView().getEditorParent());
}
});
and I put it in file GridDragDropRowOrder.js
under directory localhost\ext-4.0.7\examples\ux\dd\GridDragDropRowOrder.js
My code is under localhost\ext-4.0.7\examples\grid\security-rule.js
and looks like this :
Ext.Loader.setConfig({
enabled: true
});
Ext.Loader.setPath('Ext.ux', '../ux');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.state.*',
'Ext.form.*',
'Ext.ux.CheckColumn',
'Ext.ux.dd.GridReorderDropTarget'
]);
Ext.onReady(function(){
// Define our data model
Ext.define('Rule', {
extend: 'Ext.data.Model',
fields: [
{name: 'number', type: 'float'},
{name: 'track'},
{name: 'comment', type: 'string'},
{ name: 'active', type: 'bool' }
]
});
// Generate mock rule data
var data = (function() {
var comments = ['Hit', 'The', 'Road', 'Jack', 'And', 'Dont', 'You', 'Come', 'Back', 'No', 'More'],
commentslen = comments.length,
data = [],
start = 0,
end = 20,
getRandomInt = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
generateComment = function() {
var name = comments[getRandomInt(0, commentslen - 1)];
return name;
};
while (start < end) {
var name = generateComment();
data.push({
number:start+1,
track : 'Alert',
comment: name.toLowerCase().replace(' ', '.'),
active: getRandomInt(0, 1)
});
start = start+1;
}
return data;
})();
// create the Data Store
var store = Ext.create('Ext.data.Store', {
// destroy the store if the grid is destroyed
autoDestroy: true,
model: 'Rule',
proxy: {
type: 'memory'
},
data: data,
sorters: [{
property: 'number',
direction: 'ASC'
}]
});
var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false
});
// create the grid and specify what field you want
// to use for the editor at each column.
var grid = Ext.create('Ext.grid.Panel', {
xtype:"grid",
store: store,
columns: [
new Ext.grid.RowNumberer(),
{
header: 'Rule Number',
dataIndex: 'number',
width: 70,
align: 'right',
editor: {
xtype: 'numberfield',
allowBlank: false,
minValue: 1,
maxValue: 100000
}
},
{
header: 'Track',
dataIndex: 'track',
width: 130,
editor: {
xtype: 'combobox',
typeAhead: true,
triggerAction: 'all',
selectOnTab: true,
store: [
['Alert','Alert'],
['None','None'],
['Log','Log']
],
lazyRender: true,
listClass: 'x-combo-list-small'
}
},
{
header: 'Comment',
dataIndex: 'comment',
flex: 1,
editor: {
// defaults to textfield if no xtype is supplied
allowBlank: false
}
},
{
xtype: 'checkcolumn',
header: 'Active?',
dataIndex: 'active',
width: 60,
editor: {
xtype: 'checkbox',
cls: 'x-grid-checkheader-editor'
}
},
{
xtype: 'actioncolumn',
header: 'Remove Rule',
items: [
{
xtype: 'button',
icon: '../shared/icons/fam/delete.gif',
tooltip: 'Delete',
handler: function(grid, rowIndex, colIndex)
{
var rec = grid.getStore().getAt(rowIndex);
rowEditing.cancelEdit();
store.remove(rec);
if (store.getCount() > 0) {
sm.select(0);
}
}
}
]
}],
renderTo: 'editor-grid',
width: 600,
height: 400,
title: 'Security Rule Bar',
frame: true,
tbar: [{
text: 'Add Rule',
icon: '../shared/icons/fam/add.gif',
handler : function() {
rowEditing.cancelEdit();
// Create a model instance
var r = Ext.create('Rule', {
number: 1,
track: 'Alert',
comment: 'New One',
active: true
});
store.insert(0, r);
rowEditing.startEdit(0, 0);
}
}, {
itemId: 'removeRule',
text: 'Remove Rule',
icon: '../shared/icons/fam/cross.gif',
handler: function() {
var sm = grid.getSelectionModel();
rowEditing.cancelEdit();
store.remove(sm.getSelection());
if (store.getCount() > 0) {
sm.select(0);
}
},
disabled: true
}],
plugins: [rowEditing],
[new Ext.ux.dd.GridDragDropRowOrder(
{
copy: false, // false by default
scrollable: true, // enable scrolling support (default is false)
targetCfg: { track }, // any properties to apply to the actual DropTarget
listeners: {
'afterrowmove': //change to 'afterrowcopy' if copy=true
{
fn: function() {
this.grid.store.fireEvent('datachanged', this.grid.store);
}
}
}
})],
listeners: {
'selectionchange': function(view, records) {
grid.down('#removeRule').setDisabled(!records.length);
}
}
});
});
---------------------------------------------------------------------------------------------------------
when i added the plugin [new Ext.ux.dd.GridDragDropRowOrder(....
it didn't work. am I missing something ? should i attach the plugin to something ?
Thanks
http://www.sencha.com/forum/showthread.php?21913-SOLVED-Grid-Drag-and-Drop-reorder-rows/page8
Ext.namespace('Ext.ux.dd');
Ext.ux.dd.GridDragDropRowOrder = Ext.extend(Ext.util.Observable,
{
copy: false,
scrollable: false,
constructor : function(config)
{
if (config)
Ext.apply(this, config);
this.addEvents(
{
beforerowmove: true,
afterrowmove: true,
beforerowcopy: true,
afterrowcopy: true
});
Ext.ux.dd.GridDragDropRowOrder.superclass.constructor.call(this);
},
init : function (grid)
{
this.grid = grid;
grid.enableDragDrop = true;
grid.on({
render: { fn: this.onGridRender, scope: this, single: true }
});
},
onGridRender : function (grid)
{
var self = this;
this.target = new Ext.dd.DropTarget(grid.getEl(),
{
ddGroup: grid.ddGroup || 'GridDD',
grid: grid,
gridDropTarget: this,
notifyDrop: function(dd, e, data)
{
// Remove drag lines. The 'if' condition prevents null error when drop occurs without dragging out of the selection area
if (this.currentRowEl)
{
this.currentRowEl.removeClass('grid-row-insert-below');
this.currentRowEl.removeClass('grid-row-insert-above');
}
// determine the row
var t = Ext.lib.Event.getTarget(e);
var rindex = this.grid.getView().findRowIndex(t);
if (rindex === false || rindex == data.rowIndex)
{
return false;
}
// fire the before move/copy event
if (this.gridDropTarget.fireEvent(self.copy ? 'beforerowcopy' : 'beforerowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections, 123) === false)
{
return false;
}
// update the store
var ds = this.grid.getStore();
// Changes for multiselction by Spirit
var selections = new Array();
var keys = ds.data.keys;
for (var key in keys)
{
for (var i = 0; i < data.selections.length; i++)
{
if (keys[key] == data.selections[i].id)
{
// Exit to prevent drop of selected records on itself.
if (rindex == key)
{
return false;
}
selections.push(data.selections[i]);
}
}
}
// fix rowindex based on before/after move
if (rindex > data.rowIndex && this.rowPosition < 0)
{
rindex--;
}
if (rindex < data.rowIndex && this.rowPosition > 0)
{
rindex++;
}
// fix rowindex for multiselection
if (rindex > data.rowIndex && data.selections.length > 1)
{
rindex = rindex - (data.selections.length - 1);
}
// we tried to move this node before the next sibling, we stay in place
if (rindex == data.rowIndex)
{
return false;
}
// fire the before move/copy event
/* dupe - does it belong here or above???
if (this.gridDropTarget.fireEvent(self.copy ? 'beforerowcopy' : 'beforerowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections, 123) === false)
{
return false;
}
*/
if (!self.copy)
{
for (var i = 0; i < data.selections.length; i++)
{
ds.remove(ds.getById(data.selections[i].id));
}
}
for (var i = selections.length - 1; i >= 0; i--)
{
var insertIndex = rindex;
ds.insert(insertIndex, selections[i]);
}
// re-select the row(s)
var sm = this.grid.getSelectionModel();
if (sm)
{
sm.selectRecords(data.selections);
}
// fire the after move/copy event
this.gridDropTarget.fireEvent(self.copy ? 'afterrowcopy' : 'afterrowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections);
return true;
},
notifyOver: function(dd, e, data)
{
var t = Ext.lib.Event.getTarget(e);
var rindex = this.grid.getView().findRowIndex(t);
// Similar to the code in notifyDrop. Filters for selected rows and quits function if any one row matches the current selected row.
var ds = this.grid.getStore();
var keys = ds.data.keys;
for (var key in keys)
{
for (var i = 0; i < data.selections.length; i++)
{
if (keys[key] == data.selections[i].id)
{
if (rindex == key)
{
if (this.currentRowEl)
{
this.currentRowEl.removeClass('grid-row-insert-below');
this.currentRowEl.removeClass('grid-row-insert-above');
}
return this.dropNotAllowed;
}
}
}
}
// If on first row, remove upper line. Prevents negative index error as a result of rindex going negative.
if (rindex < 0 || rindex === false)
{
this.currentRowEl.removeClass('grid-row-insert-above');
return this.dropNotAllowed;
}
try
{
var currentRow = this.grid.getView().getRow(rindex);
// Find position of row relative to page (adjusting for grid's scroll position)
var resolvedRow = new Ext.Element(currentRow).getY() - this.grid.getView().scroller.dom.scrollTop;
var rowHeight = currentRow.offsetHeight;
// Cursor relative to a row. -ve value implies cursor is above the row's middle and +ve value implues cursor is below the row's middle.
this.rowPosition = e.getPageY() - resolvedRow - (rowHeight/2);
// Clear drag line.
if (this.currentRowEl)
{
this.currentRowEl.removeClass('grid-row-insert-below');
this.currentRowEl.removeClass('grid-row-insert-above');
}
if (this.rowPosition > 0)
{
// If the pointer is on the bottom half of the row.
this.currentRowEl = new Ext.Element(currentRow);
this.currentRowEl.addClass('grid-row-insert-below');
}
else
{
// If the pointer is on the top half of the row.
if (rindex - 1 >= 0)
{
var previousRow = this.grid.getView().getRow(rindex - 1);
this.currentRowEl = new Ext.Element(previousRow);
this.currentRowEl.addClass('grid-row-insert-below');
}
else
{
// If the pointer is on the top half of the first row.
this.currentRowEl.addClass('grid-row-insert-above');
}
}
}
catch (err)
{
console.warn(err);
rindex = false;
}
return (rindex === false)? this.dropNotAllowed : this.dropAllowed;
},
notifyOut: function(dd, e, data)
{
// Remove drag lines when pointer leaves the gridView.
if (this.currentRowEl)
{
this.currentRowEl.removeClass('grid-row-insert-above');
this.currentRowEl.removeClass('grid-row-insert-below');
}
}
});
if (this.targetCfg)
{
Ext.apply(this.target, this.targetCfg);
}
if (this.scrollable)
{
Ext.dd.ScrollManager.register(grid.getView().getEditorParent());
grid.on({
beforedestroy: this.onBeforeDestroy,
scope: this,
single: true
});
}
},
getTarget: function()
{
return this.target;
},
getGrid: function()
{
return this.grid;
},
getCopy: function()
{
return this.copy ? true : false;
},
setCopy: function(b)
{
this.copy = b ? true : false;
},
onBeforeDestroy : function (grid)
{
// if we previously registered with the scroll manager, unregister
// it (if we don't it will lead to problems in IE)
Ext.dd.ScrollManager.unregister(grid.getView().getEditorParent());
}
});
and I put it in file GridDragDropRowOrder.js
under directory localhost\ext-4.0.7\examples\ux\dd\GridDragDropRowOrder.js
My code is under localhost\ext-4.0.7\examples\grid\security-rule.js
and looks like this :
Ext.Loader.setConfig({
enabled: true
});
Ext.Loader.setPath('Ext.ux', '../ux');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.state.*',
'Ext.form.*',
'Ext.ux.CheckColumn',
'Ext.ux.dd.GridReorderDropTarget'
]);
Ext.onReady(function(){
// Define our data model
Ext.define('Rule', {
extend: 'Ext.data.Model',
fields: [
{name: 'number', type: 'float'},
{name: 'track'},
{name: 'comment', type: 'string'},
{ name: 'active', type: 'bool' }
]
});
// Generate mock rule data
var data = (function() {
var comments = ['Hit', 'The', 'Road', 'Jack', 'And', 'Dont', 'You', 'Come', 'Back', 'No', 'More'],
commentslen = comments.length,
data = [],
start = 0,
end = 20,
getRandomInt = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
generateComment = function() {
var name = comments[getRandomInt(0, commentslen - 1)];
return name;
};
while (start < end) {
var name = generateComment();
data.push({
number:start+1,
track : 'Alert',
comment: name.toLowerCase().replace(' ', '.'),
active: getRandomInt(0, 1)
});
start = start+1;
}
return data;
})();
// create the Data Store
var store = Ext.create('Ext.data.Store', {
// destroy the store if the grid is destroyed
autoDestroy: true,
model: 'Rule',
proxy: {
type: 'memory'
},
data: data,
sorters: [{
property: 'number',
direction: 'ASC'
}]
});
var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false
});
// create the grid and specify what field you want
// to use for the editor at each column.
var grid = Ext.create('Ext.grid.Panel', {
xtype:"grid",
store: store,
columns: [
new Ext.grid.RowNumberer(),
{
header: 'Rule Number',
dataIndex: 'number',
width: 70,
align: 'right',
editor: {
xtype: 'numberfield',
allowBlank: false,
minValue: 1,
maxValue: 100000
}
},
{
header: 'Track',
dataIndex: 'track',
width: 130,
editor: {
xtype: 'combobox',
typeAhead: true,
triggerAction: 'all',
selectOnTab: true,
store: [
['Alert','Alert'],
['None','None'],
['Log','Log']
],
lazyRender: true,
listClass: 'x-combo-list-small'
}
},
{
header: 'Comment',
dataIndex: 'comment',
flex: 1,
editor: {
// defaults to textfield if no xtype is supplied
allowBlank: false
}
},
{
xtype: 'checkcolumn',
header: 'Active?',
dataIndex: 'active',
width: 60,
editor: {
xtype: 'checkbox',
cls: 'x-grid-checkheader-editor'
}
},
{
xtype: 'actioncolumn',
header: 'Remove Rule',
items: [
{
xtype: 'button',
icon: '../shared/icons/fam/delete.gif',
tooltip: 'Delete',
handler: function(grid, rowIndex, colIndex)
{
var rec = grid.getStore().getAt(rowIndex);
rowEditing.cancelEdit();
store.remove(rec);
if (store.getCount() > 0) {
sm.select(0);
}
}
}
]
}],
renderTo: 'editor-grid',
width: 600,
height: 400,
title: 'Security Rule Bar',
frame: true,
tbar: [{
text: 'Add Rule',
icon: '../shared/icons/fam/add.gif',
handler : function() {
rowEditing.cancelEdit();
// Create a model instance
var r = Ext.create('Rule', {
number: 1,
track: 'Alert',
comment: 'New One',
active: true
});
store.insert(0, r);
rowEditing.startEdit(0, 0);
}
}, {
itemId: 'removeRule',
text: 'Remove Rule',
icon: '../shared/icons/fam/cross.gif',
handler: function() {
var sm = grid.getSelectionModel();
rowEditing.cancelEdit();
store.remove(sm.getSelection());
if (store.getCount() > 0) {
sm.select(0);
}
},
disabled: true
}],
plugins: [rowEditing],
[new Ext.ux.dd.GridDragDropRowOrder(
{
copy: false, // false by default
scrollable: true, // enable scrolling support (default is false)
targetCfg: { track }, // any properties to apply to the actual DropTarget
listeners: {
'afterrowmove': //change to 'afterrowcopy' if copy=true
{
fn: function() {
this.grid.store.fireEvent('datachanged', this.grid.store);
}
}
}
})],
listeners: {
'selectionchange': function(view, records) {
grid.down('#removeRule').setDisabled(!records.length);
}
}
});
});
---------------------------------------------------------------------------------------------------------
when i added the plugin [new Ext.ux.dd.GridDragDropRowOrder(....
it didn't work. am I missing something ? should i attach the plugin to something ?
Thanks