PDA

View Full Version : [3.2.1] DragColumn - Grid plugin for a draggable column



ShadowZero3000
30 Sep 2010, 1:02 PM
Posting this with 3.2.1 in the subject, as I haven't tested it in anything else, but I figured I would share this plugin we had need for and may help others.

Name: DragColumn
Class: Ext.ux.grid.DragColumn
Purpose: Add a draggable column to your grid, as apposed to having the whole row be draggable (Good if you want to be able to select text in the row, but still drag it)
Kudos: Saki and his awesome RowActions Plugin, from which I based my code (Having never written a plugin before)
Demo: I may see about getting a demo loaded in the relatively near future

Usage:
Relatively simple to use, as with most plugins. Within a grid:


/* Instantiation of plugin */
var dragcol=new Ext.ux.grid.DragColumn({
ddGroup:'dd-mysheet-bo'
,getDragText:function(value,cell,record,row,col,store){
return 'Watch: '+record.data['ID'];
}
});
/* Instantiation of a grid */
{
xtype:'grid'
,cm:new Ext.grid.ColumnModel({
columns:[dragcol]
})
,plugins:[dragcol]
}
Code:
I have a css file and image I will upload later, but basically it's just a grid of dots and the following:

.icon-drag {
background-image:url("../images/grid_drag.png") !important;
}Full class (DragDrop.js) is as follows:

/**
* @class Ext.ux.grid.DragColumn
* @extends Ext.Component
*
* DragColumn plugin for Ext grid. Creates a draggable element within a column.
* CSS rules from Ext.ux.DragColumn.css are optional, and simply provide the default icon that I am using for dragging
*
* Important general information: In order to have a user-friendly drag object, you will need to override the getDragText
* function. It is provided with a 'Drag Me' text by default, but has full access to the row/store to get appropriate data.
* Thanks to Ing. Jozef Sakáloš for his exceptional examples, including this header format. Please contact me if you need further
* credit or any adjustment.
*
* @author Joshua L. Souza
* @copyright (c) 2010, by Joshua L. Souza
* @date 29. Dec 2010
* @version 1.1
*
* @license Ext.ux.grid.DragColumn is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
* target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
*
* @forum 29961
* @demo None yet
* @download
* <ul>
* <li>Yet to come</li>
* </ul>
*
* </form>
*/

Ext.ns('Ext.ux.grid');
/**
* Creates new DragColumn plugin
* @constructor
* @param {Object} config A config object
*/
Ext.ux.grid.DragColumn = function(config){
Ext.apply(this, config);
Ext.ux.grid.DragColumn.superclass.constructor.call(this);
};
Ext.extend(Ext.ux.grid.DragColumn, Ext.Component,{
editable:false
,header:''
,dataIndex:''
,iconCls:'icon-drag'
,iconStyle:'width:16;height:16'
,width:24
/**
* @cfg {Boolean} isColumn
* Tell ColumnModel that we are column. Do not touch!
* @private
*/
,isColumn:true
/**
* @cfg {Boolean} menuDisabled No sense to display header menu for this column
* @private
*/
,menuDisabled:true

/**
* @cfg {Boolean} sortable Usually it has no sense to sort by this column
* @private
*/
,sortable:false

,ddGroup:'col-drag'
/**
* Function to be overridden to edit the contents of the drag object. Use to display row information in the dragged item.
* @param {Object} value This is the dataIndex value, usually nothing
* @param {Ext.Element} cell The cell, pretty useless in this context
* @param {Ext.data.Record} record The record for this row, pull data from this
* @param {Number} row The row number
* @param {Number} col The column number
* @param {Ext.data.Store} store The original store
*/
,getDragText:function(value,cell,record,row,col,store){
return 'Drag Me';
}
/**
* The constructor for this object
* @param {Object} grid The grid we're plugging into
* @param {Object} hd
* @param {Object} hd2
*/
,constructor:function(grid,hd,hd2){
this.grid = grid;
this.view = grid.getView();
}

/**
* Init function
* @param {Ext.grid.GridPanel} grid Grid this plugin is in
*/
,init:function(grid){
this.grid=grid;
// the column must have an id for Ext 3.x
this.id = this.id || Ext.id();
// for Ext 3.x compatibility
var lookup = grid.getColumnModel().lookup;
delete(lookup[undefined]);
lookup[this.id] = this;
// body click handler
var view = grid.getView();
this.view=view;
view.on('refresh',function(){
var bod=this.view.mainBody.dom;
var cells=[];
if (bod.getElementsByClassName) {
cells = bod.getElementsByClassName('x-grid3-col-' + this.id);
}
else {
var a= bod.getElementsByTagName("div");
var L= a.length;
var tem;
while(L){
tem= a[--L];
if(tem.className.indexOf('x-grid3-col-' + this.id)!=-1) cells.push(tem);
}

}
if (cells.length > 0) {
Ext.each(cells, function(cell,index,cells){
var el=Ext.get(cell);
el=el.child('div.'+this.iconCls)
var elDragZone = new Ext.dd.DragZone(el, {
ddGroup: this.ddGroup,
// On receipt of a mousedown event, see if it is within a draggable element.
// Return a drag data object if so. The data object can contain arbitrary application
// data, but it should also contain a DOM element in the ddel property to provide
// a proxy to drag.
getDragData: function(e){
var sourceEl = Ext.get(e.target).child('div.ux-drag-contents',true);
if (sourceEl) {
d = sourceEl.cloneNode(true);
d.id = Ext.id();
return {
sourceEl: sourceEl
,repairXY: Ext.fly(e.target).getXY()
,ddel: d
,selections: grid.store.getAt(index)

}
}
return undefined;
}

// Provide coordinates for the proxy to slide back to on failed drag.
// This is the original XY coordinates of the draggable element.
,getRepairXY: function(){
return this.dragData.repairXY;
}
});
//Must add a destroy on refresh to prevent memory leaks
view.on('beforerefresh',function(){
elDragZone.destroy();
},this);
},this);
}
},this)
// setup renderer
if(!this.renderer) {
this.renderer = function(value, cell, record, row, col, store) {
var div='<div class="'+this.iconCls+'" style="'+this.iconStyle+'"><div style="display:none"><div class="ux-drag-contents">'+this.getDragText(value,cell,record,row,col,store)+'</div></div></div>';
return div;
}.createDelegate(this);
}
}

});
Ext.reg('dragcolumn',Ext.ux.grid.DragColumn);

Please help me out by trying this and informing me if you see any bugs/tweaks it needs, and let me know if it is compatible with other versions of ExtJS, as I won't have time to test it out in other versions for a while.

ShadowZero3000
22 Nov 2010, 9:06 AM
Edited the class to fix a memory leak this causes. You have to destroy the drag/drop zone on refresh, or they don't get gracefully deleted.

ShadowZero3000
29 Dec 2010, 12:10 PM
I have updated it yet again to include some handling for IE not having the 'getElementsByClassName' functionality. This has been tested and is happy with 3.3.0.