dajester2008
24 Jan 2010, 10:14 PM
I wanted an easier way to set up a rowcontextmenu on my grids, so I came up with the following:
/**
* Ext.ux.RowContextActions
*
* This plugin can be instantiated once, and applied to multiple grids. It looks
* for an additional set of params specified on the grid (rowContextActions),
* or for a set of 'contextActions' defined on the plugin itself.
*/
Ext.ux.RowContextActions = function(config) {
Ext.apply(this,config);
}
Ext.ux.RowContextActions.prototype = {
init:function(grid) {
grid.rowContextActions = grid.rowContextActions || this.contextActions || [];
grid.menu = new Ext.menu.Menu(this.menuCfg);
grid.menu.grid = grid;
grid.on('rowcontextmenu',grid.menu.open,grid.menu);
grid.on('bodyscroll',grid.menu.onScroll,grid.menu);
grid.menu.on('hide',grid.menu.reset);
}
/**
* Everything below here is operated in the context of the menu that gets
* appended to the grid.
*/
,menuCfg:{
curRowIdx:null
,curRecord:null
,curEvt:null
,grid:null
,curRowDom:null
,width:200
,enableScrolling:false
,open:function(grid,ri,e) {
this.removeAll();
this.curEvt = e;
this.curRowIdx = ri;
this.curRecord = grid.store.getAt(ri);
this.doLoadItems();
if (!this.showable) { return this.hide(); }
this.curRowDom = grid.getView().getRow(ri);
e.stopEvent();
this.showAt([e.getPoint()[0],Ext.fly(this.curRowDom).getBottom()-1]);
this.checkPosition();
this.visible=true;
}
,doLoadItems:function() {
var g = this.grid,
ri= this.curRowIdx,
e = this.curEvt,
r = this.curRecord;
this.showable=false;
Ext.each(this.grid.rowContextActions,function(actn) {
var newItem={};
if (typeof actn == 'string') {
this.add(actn);
return true;
}
Ext.apply(newItem,actn);
if (typeof actn.getText === 'function')
newItem.text = actn.getText(g,ri,e,r);
else
newItem.text = actn.text;
if (typeof actn.getDisabled === 'function')
newItem.disabled = actn.getDisabled(g,ri,e,r);
newItem.userHandler = actn.handler || actn.userHandler || Ext.emptyFn;
newItem.handler = function(item,cEvt) {
item.userHandler(item,cEvt,r,g,ri);
}
actn.beforeAdd = actn.beforeAdd || function() {return true;};
if (actn.beforeAdd(g,ri,e,r) !== false) {
this.add(newItem);
this.showable=true;
}
},this);
}
,onScroll:function() {
if (!this.visible) return;
if (!this.checkRowVisible()) {
this.hide();
return;
}
this.checkPosition();
}
,checkRowVisible:function() {
return (Ext.fly(this.curRowDom).getBottom() > this.grid.getView().scroller.getTop()
&&
Ext.fly(this.curRowDom).getTop() < this.grid.getView().scroller.getBottom());
}
,checkPosition:function() {
this.el.setTop(Ext.fly(this.curRowDom).getBottom()-1);
this.curRowDom.style.borderTop = '1px solid #aaa';
this.curRowDom.style.borderBottom = '1px solid #aaa';
// make both borders are there
this.el.dom.style.borderTop = '1px solid #aaa';
this.el.dom.style.borderBottom = '1px solid #aaa';
// remove top border
this.el.dom.style.borderTop=0;
this.el.dom.style.backgroundColor = '#eee';
this.curRowDom.style.backgroundColor = '#eee';
// make sure its over to the left far enough
var rightConstraint = Ext.fly(this.curRowDom).getRight()-5;
if (rightConstraint > (this.el.getWidth()+5) && this.el.getRight() > rightConstraint) {
this.el.setLeft(rightConstraint-this.el.getWidth());
}
this.el.shadow.realign(this.el.getLeft(),this.el.getTop(),this.el.getWidth(),this.el.getHeight());
if (this.el.getBottom() > this.grid.getView().scroller.getBottom()) {
this.el.setTop(Ext.fly(this.curRowDom).getTop()-this.el.getHeight()+1);
this.el.dom.style.borderTop='1px solid #aaa';
this.el.dom.style.borderBottom=0;
this.el.shadow.realign(this.el.getLeft(),this.el.getTop()-3,this.el.getWidth(),this.el.getHeight());
}
}
,reset:function() {
if (this.curRowDom) {
this.curRowDom.style.backgroundColor = '';
this.curRowDom.style.borderTop = '';
this.curRowDom.style.borderBottom = '';
}
this.curRowIdx=null;
this.curRecord=null;
this.curEvt=null;
this.curRowDom=null;
this.visible=false;
}
}
}
Example use:
var rowCtxActions = new Ext.ux.RowContextActions();
var myGrid = new Ext.grid.GridPanel(
// just MenuItems with some additional configuration...
plugins:[rowCtxActions]
,rowContextActions:[
{
text:'Edit User' // or use 'getText:function(grid,ri,e,rec) {}' to return the text to use for this item'
,getDisabled:function(grid,ri,e,rec) { /*return true to disable this item*/ }
,beforeAdd:function(grid,ri,e,rec) { /*return false to keep from adding this item*/ }
,icon:'path-to-icon'
,handler:function(item,event,record,grid,ri) {
//do your thing here...
}
}
]
)
Hopefully someone else will also find this useful.
/**
* Ext.ux.RowContextActions
*
* This plugin can be instantiated once, and applied to multiple grids. It looks
* for an additional set of params specified on the grid (rowContextActions),
* or for a set of 'contextActions' defined on the plugin itself.
*/
Ext.ux.RowContextActions = function(config) {
Ext.apply(this,config);
}
Ext.ux.RowContextActions.prototype = {
init:function(grid) {
grid.rowContextActions = grid.rowContextActions || this.contextActions || [];
grid.menu = new Ext.menu.Menu(this.menuCfg);
grid.menu.grid = grid;
grid.on('rowcontextmenu',grid.menu.open,grid.menu);
grid.on('bodyscroll',grid.menu.onScroll,grid.menu);
grid.menu.on('hide',grid.menu.reset);
}
/**
* Everything below here is operated in the context of the menu that gets
* appended to the grid.
*/
,menuCfg:{
curRowIdx:null
,curRecord:null
,curEvt:null
,grid:null
,curRowDom:null
,width:200
,enableScrolling:false
,open:function(grid,ri,e) {
this.removeAll();
this.curEvt = e;
this.curRowIdx = ri;
this.curRecord = grid.store.getAt(ri);
this.doLoadItems();
if (!this.showable) { return this.hide(); }
this.curRowDom = grid.getView().getRow(ri);
e.stopEvent();
this.showAt([e.getPoint()[0],Ext.fly(this.curRowDom).getBottom()-1]);
this.checkPosition();
this.visible=true;
}
,doLoadItems:function() {
var g = this.grid,
ri= this.curRowIdx,
e = this.curEvt,
r = this.curRecord;
this.showable=false;
Ext.each(this.grid.rowContextActions,function(actn) {
var newItem={};
if (typeof actn == 'string') {
this.add(actn);
return true;
}
Ext.apply(newItem,actn);
if (typeof actn.getText === 'function')
newItem.text = actn.getText(g,ri,e,r);
else
newItem.text = actn.text;
if (typeof actn.getDisabled === 'function')
newItem.disabled = actn.getDisabled(g,ri,e,r);
newItem.userHandler = actn.handler || actn.userHandler || Ext.emptyFn;
newItem.handler = function(item,cEvt) {
item.userHandler(item,cEvt,r,g,ri);
}
actn.beforeAdd = actn.beforeAdd || function() {return true;};
if (actn.beforeAdd(g,ri,e,r) !== false) {
this.add(newItem);
this.showable=true;
}
},this);
}
,onScroll:function() {
if (!this.visible) return;
if (!this.checkRowVisible()) {
this.hide();
return;
}
this.checkPosition();
}
,checkRowVisible:function() {
return (Ext.fly(this.curRowDom).getBottom() > this.grid.getView().scroller.getTop()
&&
Ext.fly(this.curRowDom).getTop() < this.grid.getView().scroller.getBottom());
}
,checkPosition:function() {
this.el.setTop(Ext.fly(this.curRowDom).getBottom()-1);
this.curRowDom.style.borderTop = '1px solid #aaa';
this.curRowDom.style.borderBottom = '1px solid #aaa';
// make both borders are there
this.el.dom.style.borderTop = '1px solid #aaa';
this.el.dom.style.borderBottom = '1px solid #aaa';
// remove top border
this.el.dom.style.borderTop=0;
this.el.dom.style.backgroundColor = '#eee';
this.curRowDom.style.backgroundColor = '#eee';
// make sure its over to the left far enough
var rightConstraint = Ext.fly(this.curRowDom).getRight()-5;
if (rightConstraint > (this.el.getWidth()+5) && this.el.getRight() > rightConstraint) {
this.el.setLeft(rightConstraint-this.el.getWidth());
}
this.el.shadow.realign(this.el.getLeft(),this.el.getTop(),this.el.getWidth(),this.el.getHeight());
if (this.el.getBottom() > this.grid.getView().scroller.getBottom()) {
this.el.setTop(Ext.fly(this.curRowDom).getTop()-this.el.getHeight()+1);
this.el.dom.style.borderTop='1px solid #aaa';
this.el.dom.style.borderBottom=0;
this.el.shadow.realign(this.el.getLeft(),this.el.getTop()-3,this.el.getWidth(),this.el.getHeight());
}
}
,reset:function() {
if (this.curRowDom) {
this.curRowDom.style.backgroundColor = '';
this.curRowDom.style.borderTop = '';
this.curRowDom.style.borderBottom = '';
}
this.curRowIdx=null;
this.curRecord=null;
this.curEvt=null;
this.curRowDom=null;
this.visible=false;
}
}
}
Example use:
var rowCtxActions = new Ext.ux.RowContextActions();
var myGrid = new Ext.grid.GridPanel(
// just MenuItems with some additional configuration...
plugins:[rowCtxActions]
,rowContextActions:[
{
text:'Edit User' // or use 'getText:function(grid,ri,e,rec) {}' to return the text to use for this item'
,getDisabled:function(grid,ri,e,rec) { /*return true to disable this item*/ }
,beforeAdd:function(grid,ri,e,rec) { /*return false to keep from adding this item*/ }
,icon:'path-to-icon'
,handler:function(item,event,record,grid,ri) {
//do your thing here...
}
}
]
)
Hopefully someone else will also find this useful.