PDA

View Full Version : SingleRowSelectionModel for GridPanel



litera
8 Apr 2008, 8:30 AM
Single row selection model (SingleRowSelectionModel) works different than RowSelectionModel (singleSelect = true). My version fires following events:

beforerowselect
beforerowdeselect - new event
rowselect
rowdeselect
selectionchange


Regular RowSelectionModel downsides:

fires too many events when singleSelect is used, because it actually fires selects and deselect for every row when we do Shift+click
doesn't have the beforerowdeselect event that is added here
fires rowselected and rowdeselected every time there's a selection change (sequence being: deselect, change, select, change). This one just fires selectionchange


This selection model uses a different approach:

When you first select a row, rowselected(selModel, index, record) is fired
If you select a different row, selectionchange(selModel, newIndex, newRecord, oldIndex, oldRecord) is fired
If you Ctrl+click on a selected row, rowdeselected(selModel, index, record) is fired
Shift+click behaves as expected: it only fires either a rowselected (when nothing has been selected so far) or selectionchange (if there's a selection change)


So here's the code. Use it at your own risk ;)


Ext.ux.SingleRowSelectionModel = function(config){
Ext.apply(this, config);

this.selectedRow = null;
this.selectedIndex = -1;

this.addEvents(

// params: selectionModel, index, record
"beforerowselect",
// params: selectionModel, index, record
"beforerowdeselect",

// params: selectionModel, index, record
"rowselect",
// params: selectionModel, index, record
"rowdeselect",

//params: selectionModel, newIndex, newRecord, oldIndex, oldRecord
"selectionchange"
);

Ext.ux.SingleRowSelectionModel.superclass.constructor.call(this);
};

Ext.extend(Ext.ux.SingleRowSelectionModel, Ext.grid.AbstractSelectionModel, {

selectedRow: null,
selectedIndex: -1,

initEvents : function(){

if (this.grid.enableDragDrop || this.grid.enableDrag){
this.grid.enableDragDrop = false;
}
this.grid.on("rowmousedown", this.handleMouseDown, this);

this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
"up" : function(e){
if (this.selectedIndex > 0)
this.selectPrevious();
},
"down" : function(e){
if (this.selectedIndex < this.grid.store.getCount() - 1)
this.selectNext();
},
scope: this
});

var view = this.grid.view;
view.on("refresh", this.onViewRefresh, this);
view.on("rowupdated", this.onViewRowUpdated, this);
view.on("rowremoved", this.onViewRowRemove, this);
},

getCount: function(){
return this.selectedRow === null ? 0 : 1;
},

onViewRefresh : function(view){
var ds = this.grid.store;
var row = this.selectedRow;
var index = this.selectedIndex;
if (this.selectedIndex != -1 && this.selectedRow !== null){
this.deselectRow(index);
}
},

onViewRowRemove : function(view, index, record){
if (this.selectedIndex == index){
this.deselectRow(index);
}
},

onViewRowUpdated : function(view, index, record){
if(this.selectedIndex == index){
view.onRowSelect(index);
}
},

selectRow : function(index, preventViewNotify){
if(this.locked || (index < 0 || index >= this.grid.store.getCount())) return;
var record = this.grid.store.getAt(index);
// select row and fire appropriate events
if (this.selectedRow !== record){
if (record && this.fireEvent("beforerowselect", this, index, record) !== false)
{
if(!preventViewNotify){
if (this.selectedRow !== null){
this.grid.getView().onRowDeselect(this.selectedIndex);
}
this.grid.getView().onRowSelect(index);
}
// is it a selection change or an actual selection
if (this.selectedIndex != -1 && this.selectedRow !== null)
this.fireEvent("selectionchange", this, index, record, this.selectedIndex, this.selectedRow);
else
this.fireEvent("rowselect", this, index, record);
// store selection
this.selectedRow = record;
this.selectedIndex = index;
}
}
else{
if (record && this.fireEvent("beforerowselect", this, index, record) !== false){
this.fireEvent("rowselect", this, index, record);
}
}
},

deselectRow : function(index, preventViewNotify){
if(this.locked) return;
var record = this.grid.store.getAt(index);
if (record && this.fireEvent("beforerowdeselect", this, index, record) !== false){
if(!preventViewNotify){
this.grid.getView().onRowDeselect(index);
}
this.fireEvent("rowdeselect", this, index, record);
// forget selection
this.selectedRow = null;
this.selectedIndex = -1;
}
},

clearSelection : function(fast){
if (this.locked) return;
if (fast !== true){
if (this.selectedRow !== null && this.selectedIndex != -1)
this.deselectRow(this.selectedIndex);
}
else {
this.selectedRow = null;
this.selectedIndex = -1;
}
},

handleMouseDown : function(g, index, e){
if(e.button !== 0 || this.locked) return;
if(e.ctrlKey && this.selectedIndex == index){
this.deselectRow(index);
}
else {
this.selectRow(index);
this.grid.getView().focusRow(index);
}
},

selectFirstRow : function(){
this.selectRow(0);
},

selectLastRow : function(){
var lastIndex = this.grid.store.getCount() - 1;
this.selectRow(lastIndex);
},

selectNext : function(){
if(this.hasNext()){
this.selectRow(this.selectedIndex + 1);
this.grid.getView().focusRow(this.selectedIndex);
}
},

selectPrevious : function(){
if(this.hasPrevious()){
this.selectRow(this.selectedIndex - 1);
this.grid.getView().focusRow(this.selectedIndex);
}
},

hasNext : function(){
return this.selectedIndex !== -1 && (this.selectedIndex + 1) < this.grid.store.getCount();
},

hasPrevious : function(){
return this.selectedIndex > 0;
},

getSelected : function(){
return this.selectedRow;
},

hasSelection : function(){
return this.selectedRow !== null;
},

isSelected : function(index){
return (this.selectedIndex == index);
},

isIdSelected : function(id){
return (this.selectedRow !== null && this.selectedRow.id == id);
},

acceptsNav : function(row, col, cm){
return !cm.isHidden(col) && cm.isCellEditable(col, row);
},

onEditorKey : function(field, e){
var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
if(k == e.TAB){
e.stopEvent();
ed.completeEdit();
if(e.shiftKey){
newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
}else{
newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
}
}else if(k == e.ENTER){
e.stopEvent();
ed.completeEdit();
if(e.shiftKey){
newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
}else{
newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
}
}else if(k == e.ESC){
ed.cancelEdit();
}
if(newCell){
g.startEditing(newCell[0], newCell[1]);
}
}
});

seldon
25 Apr 2008, 8:40 AM
Thanks! This is exactly what I was looking for. Nice job!