PDA

View Full Version : Ext.PagingToolbar with Filter Window using Ext.ux.grid.RowEditor (override)



jorgelive
19 Oct 2010, 7:16 AM
22917
Hi, I was looking for a extension who filters like jqgrid's advanced filter does (I'm migrating from it), with no results (I guess I't doesn't exist), my customers didn't like column filter extension, then a litle override in the paging toolbar do the job (I'm using ext 3.2).

It uses a modified Ext.ux.grid.RowEditor, I was modifying this extension because I needed some features like permisions from database (not for filters), delete record on creation cancelled (filter override need this),

Notes:
1. you can with a litle codding make it work with the clean version of Ext.ux.grid.RowEditor.
2. The strings are in spanish (I'm peruvian), you can tranlate it.
3. Conditionals were made thinking in Cakephp backend so equal is empty, lower than is ' <'
4. There are some php strings from cake that you have to replace.

Here comes the code

The store needs in it's fields a property called filtername :



var noticiaStore = new Ext.data.JsonStore({
,url: anyurl
,root: 'noticias'
,totalProperty: 'total'
,fields: [{
name: 'id'
},{
name: 'title'
,filterName:'Titulo' //==============>This is a parameter
},{
name: 'imagen'
},{
name: 'contenido'
,filterName:'Contenido'
},{
name: 'fecha'
,filterName: 'Fecha' //==============>This is a parameter
,type: 'date'
,dateFormat: 'Y-m-d'
},{
name: 'borrar_imagen'
,type: 'boolean'
},{
name: 'idioma'
},{
name: 'permiso'
}]
,remoteSort:true
,sortInfo: {
field: 'fecha'
,direction: 'DESC'
}
,listeners:{ //==============>This is for cakephp
'beforeload': function(store, options) {
if (!options.params.start&&!options.params.limit){
if(noticiaPanel.paginatorStart&&noticiaPanel.paginatorLimit){
options.params.start=noticiaPanel.paginatorStart;
options.params.limit=noticiaPanel.paginatorLimit;
}else{
options.params.start=0;
options.params.limit=<?php echo Configure::read('Default.paginatorSize');?>;
}
}
noticiaPanel.paginatorStart=options.params.start;
noticiaPanel.paginatorLimit=options.params.limit;
options.params.page = Math.floor(options.params.start / options.params.limit)+1;
options.params.idioma = noticiaPanel.currentIdioma;
return true;
}
}
})



the bbar needs a property 'filter' set to true.



,bbar: new Ext.PagingToolbar({
pageSize: <?php echo Configure::read('Default.paginatorSize');?>
,displayInfo: true
,filter:true //==========>this is the parameter
,store: noticiaStore
,displayMsg: 'mostrando noticias {0} - {1} de {2}'
,emptyMsg: "No hay noticis para mostrar"
})


And thats it.

Here's the override:




Ext.override(Ext.PagingToolbar, {
clearFiltersText : 'Page'
,initComponent : function(){
var T = Ext.Toolbar;
var pagingItems = [this.first = new T.Button({
tooltip: this.firstText,
overflowText: this.firstText,
iconCls: 'x-tbar-page-first',
disabled: true,
handler: this.moveFirst,
scope: this
}), this.prev = new T.Button({
tooltip: this.prevText,
overflowText: this.prevText,
iconCls: 'x-tbar-page-prev',
disabled: true,
handler: this.movePrevious,
scope: this
}), '-', this.beforePageText,
this.inputItem = new Ext.form.NumberField({
cls: 'x-tbar-page-number',
allowDecimals: false,
allowNegative: false,
enableKeyEvents: true,
selectOnFocus: true,
submitValue: false,
listeners: {
scope: this,
keydown: this.onPagingKeyDown,
blur: this.onPagingBlur
}
}), this.afterTextItem = new T.TextItem({
text: String.format(this.afterPageText, 1)
}), '-', this.next = new T.Button({
tooltip: this.nextText,
overflowText: this.nextText,
iconCls: 'x-tbar-page-next',
disabled: true,
handler: this.moveNext,
scope: this
}), this.last = new T.Button({
tooltip: this.lastText,
overflowText: this.lastText,
iconCls: 'x-tbar-page-last',
disabled: true,
handler: this.moveLast,
scope: this
}), '-', this.refresh = new T.Button({
tooltip: this.refreshText,
overflowText: this.refreshText,
iconCls: 'x-tbar-loading',
handler: this.doRefresh,
scope: this
})];

var userItems = this.items || this.buttons || [];
if (this.prependButtons) {
this.items = userItems.concat(pagingItems);
}else{
this.items = pagingItems.concat(userItems);
}
delete this.buttons;
if(this.filter){
this.items.push(this.filterItem = new T.Button({
tooltip: 'Filtros'
,overflowText: 'Filtros'
,iconCls: 'x-tbar-filtro'
,handler: this.showFilters
,scope: this

}));
this.items.push(this.clearFilterItem = new T.Button({
tooltip: 'Limpiar filtos'
,overflowText: 'Limpiar filtros'
,iconCls: 'x-tbar-borrarfiltro'
,handler: this.cleanFilters
,scope: this
}));
}
if(this.displayInfo){
this.items.push('->');
this.items.push(this.displayItem = new T.TextItem({}));
}
Ext.PagingToolbar.superclass.initComponent.call(this);
this.addEvents(
'change',
'beforechange'
);
this.on('afterlayout', this.onFirstLayout, this, {single: true});
this.cursor = 0;
this.bindStore(this.store, true);
}
,showFilters : function(){

var paginationBar=this;
var fieldData=new Array();
i=0;
for(field in this.store.fields.items) {
if(this.store.fields.items[field].filterName){
fieldData[i]=new Array();
fieldData[i].push(this.store.fields.items[field].name);
fieldData[i].push(this.store.fields.items[field].filterName);
}
i++;
}
var fieldDataJson=eval(Ext.util.JSON.encode(fieldData));

var fieldStore = new Ext.data.ArrayStore({
fields: ['field', 'name']
,listeners:{
'load':function(){
filtrosGrid.getColumnModel().getColumnById('campo').renderer=Ext.util.Format.comboRenderer(filtrosGrid.getColumnModel().getColumnById('campo').getEditor());
filtrosGrid.getColumnModel().getColumnById('operador').renderer=Ext.util.Format.arrayRenderer();
}
}
});

var numberDateOperatorData = [['','Sea igual a'],[' >','Mayor que'],[' <','Menor que'],[' >=','Mayor o igual que'],[' <=','Menor o igual que']];
var booleanOperatorData = [['','Sea igual a']];
var defaultOperatorData = [[' LIKE','Que contenga'],['','Sea igual a']];
var fechaEditor = new Ext.form.DateField({
format: 'd m Y', // 'd mmm yyyy' is not valid, but I assume this is close?
});
var booleanEditor = new Ext.form.Checkbox({});
var defaultEditor = new Ext.form.Field({});

Ext.util.Format.arrayRenderer = function(){
return function(value){
var array= new Array();
array['']='Sea igual a';
array[' LIKE']='Que contenga';
array[' >']='Mayor que';
array[' <']='Menor que';
array[' >=']='Mayor o igual que';
array[' <=']='Menor o igual que';
return array[value];
}
};

Ext.util.Format.valorFieldRenderer = function(){
return function(value){
if(typeof(value)=='object'&&value.dateFormat){
return Ext.util.Format.date(value,'d-m-Y');
}else
if(value===true){
return 'Si';
}else
if(value===false){
return 'No';
}else{
return value;
}
}
};

var operadorStore = new Ext.data.ArrayStore({
fields: ['operador', 'name']
});

if(!this.filterStore){
this.filterStore=new Ext.data.SimpleStore({
fields: ['campo', 'operador']
,data: []
//,data: [['title',''],['contenido',' >=']]
,autoLoad: true
});
}

var filtrosEditor = new Ext.ux.grid.RowEditor({
commitChangesText: 'Actualice o cancele antes de editar otro filtro'
,listeners: {
'beforeedit': function(editor,rowIndex) {
if(!this.agregando){
filterGridAcccion(editor.grid.getStore().getAt(rowIndex).data['campo']);
}
}
,'afteredit': function(editor,rowIndex) {
editor.grid.getStore().commitChanges();
}
}
});
var filtrosGrid = new Ext.grid.GridPanel({
store: paginationBar.filterStore
,loadMask: {msg:'Cargando Datos...'}
,bbar: [{
ref: '../aplicarBtn'
,tooltip: 'Aplicar filtro'
,overflowText: 'Aplicar filtro'
,iconCls: 'x-tbar-aplicar'
,handler: function(){
paginationBar.doRefresh();
}
},{
tooltip: 'Agregar filtro'
,overflowText: 'Agregar filtro'
,iconCls: 'x-tbar-agregarfiltro'
,handler: function(){
var Filtro = Ext.data.Record.create([
{
name: 'campo'
,type: 'string'
},{
name: 'operador'
,type: 'string'

},{
name: 'valor'
,type: 'string'

}]);
var newRecord = new Filtro({
campo:''
,operador: ''
,valor: ''
});
filtrosEditor.stopEditing();
paginationBar.filterStore.insert(0, newRecord);
filtrosGrid.getView().refresh();
filtrosGrid.getSelectionModel().selectRow(0);
filtrosEditor.agregando=true;
filtrosEditor.startEditing(0);
}
},{
ref: '../modificarBtn'
,tooltip: 'Modificar filtro'
,overflowText: 'Modificar filtro'
,iconCls: 'x-tbar-modificarfiltro'
,disabled: true
,handler: function(){
filtrosEditor.startEditing(filtrosGrid.getSelectionModel().getSelections()[0]);
}
},{
ref: '../removeBtn'
,tooltip: 'Borrar filtro'
,overflowText: 'Borrar filtro'
,iconCls: 'x-tbar-borrarfiltro'
,disabled: true
,handler: function(){
var rowIndex = filtrosGrid.getStore().indexOf(filtrosGrid.getSelectionModel().getSelections()[0]);
filtrosGrid.getStore().removeAt(rowIndex);
filtrosGrid.getView().refresh();
}
}]
,columns: [
{
header: 'Campo'
,id:'campo'
,width: 80
,dataIndex: 'campo'
,editor: new Ext.form.ComboBox({
hiddenName: 'campo'
,store: fieldStore
,displayField: 'name'
,valueField: 'field'
,typeAhead: true
,mode: 'local'
,triggerAction: 'all'
,emptyText: 'Seleccione'
,selectOnFocus:true
,allowBlank: false
,blankText:'Ingrese el campo'
,valueNotFoundText: ''
,listeners:{
'select':function(editor){
filterGridAcccion(editor.value);
}
}
})
},{
header: 'Operador'
,id:'operador'
,dataIndex: 'operador'
,width: 120
,editor: new Ext.form.ComboBox({
hiddenName: 'campo'
,store: operadorStore
,displayField: 'name'
,valueField: 'operador'
,typeAhead: true
,mode: 'local'
,triggerAction: 'all'
,emptyText: 'Seleccione'
,selectOnFocus:true
,allowBlank: false
,blankText:'Ingrese el operador'
,valueNotFoundText: ''
})
},{
header: 'Valor'
,id:'valor'
,dataIndex: 'valor'
,width: 80
,editor: false
,renderer: Ext.util.Format.valorFieldRenderer()
}]
,plugins: [filtrosEditor]
,stripeRows: true
,autoExpandColumn: 'valor'
});

var filtrosMenuContextual = new Ext.menu.Menu({
items: [
{
text: 'Modificar filtro'
,handler:filtrosGrid.modificarBtn.handler
,iconCls: 'x-menu-item-modificarfiltro'
},'-',{
text: 'Borrar filtro'
,handler:filtrosGrid.removeBtn.handler
,iconCls: 'x-menu-item-borrarfiltro'
}]
});

filtrosGrid.on('rowcontextmenu', function (grid,rowIndex,event) {
grid.getSelectionModel().selectRow(rowIndex);
event.stopEvent();
filtrosMenuContextual.showAt(event.getXY());
});

var filterGridAcccion=function(campo){
if(paginationBar.store.fields.map[campo].type.type=='date'){
operadorStore.loadData(numberDateOperatorData);
filtrosGrid.getColumnModel().getColumnById('valor').setEditor(
new Ext.form.DateField({
format: 'd-m-Y'
})
);
}else
if(paginationBar.store.fields.map[campo].type.type=='number'){
operadorStore.loadData(numberDateOperatorData);
filtrosGrid.getColumnModel().getColumnById('valor').setEditor(new Ext.form.Field({}));
}else
if(paginationBar.store.fields.map[campo].type.type=='bool'){
operadorStore.loadData(booleanOperatorData);
filtrosGrid.getColumnModel().getColumnById('valor').setEditor(new Ext.form.Checkbox({}));
}else{
operadorStore.loadData(defaultOperatorData);
filtrosGrid.getColumnModel().getColumnById('valor').setEditor(new Ext.form.Field({}));
}
filtrosEditor.refreshFields();
}

var filtrosWindow = new Ext.Window({
autoScroll:true
,title:'Filtros de busqueda'
,width: 340
,height: 200
,modal:true
,items:[filtrosGrid]
,layout: 'fit'
}).show();

fieldStore.loadData(fieldDataJson);
filtrosGrid.getSelectionModel().singleSelect=true;
filtrosGrid.getSelectionModel().on('selectionchange', function(sm){
filtrosGrid.removeBtn.setDisabled(sm.getCount() < 1);
filtrosGrid.modificarBtn.setDisabled(sm.getCount() < 1);
});
}
,cleanFilters : function(){
if(this.filterStore){
this.filterStore.removeAll();
}
this.doLoad(this.cursor);
}
,doLoad : function(start){
var o = {}, pn = this.getParams();
if(this.filter&&this.filterStore){
o['filtro']=new Array();
for(row in this.filterStore.data.items) {
o['filtro'][row]=new Array();
o['filtro'][row]=this.filterStore.data.items[row].data;
}
o['filtro']=Ext.util.JSON.encode(o['filtro']);
}
o[pn.start] = start;
o[pn.limit] = this.pageSize;
if(this.fireEvent('beforechange', this, o) !== false){
this.store.load({params:o});
}
}
});


The modified Ext.ux.grid.RowEditor



Ext.ns('Ext.ux.grid');

/**
* @class Ext.ux.grid.RowEditor
* @extends Ext.Panel
* Plugin (ptype = 'roweditor') that adds the ability to rapidly edit full rows in a grid.
* A validation mode may be enabled which uses AnchorTips to notify the user of all
* validation errors at once.
*
* @ptype roweditor
*/
Ext.ux.grid.RowEditor = Ext.extend(Ext.Panel, {
floating: true,
shadow: false,
layout: 'hbox',
cls: 'x-small-editor',
buttonAlign: 'center',
baseCls: 'x-row-editor',
elements: 'header,footer,body',
frameWidth: 5,
buttonPad: 3,
clicksToEdit: 2,
monitorValid: true,
focusDelay: 250,
errorSummary: true,
saveText: 'Guardar',
cancelText: 'Cancelar',
commitChangesText: 'Actualice o cancele antes de editar otro registro',
errorText: 'Errores',
agregando: false,
enEdicion: false,
permisos:false,
permisosText:'No tiene permisos modificar',
defaults: {
normalWidth: true
},
initComponent: function(){
Ext.ux.grid.RowEditor.superclass.initComponent.call(this);
this.addEvents(
/**
* @event beforeedit
* Fired before the row editor is activated.
* If the listener returns <tt>false</tt> the editor will not be activated.
* @param {Ext.ux.grid.RowEditor} roweditor This object
* @param {Number} rowIndex The rowIndex of the row just edited
*/
'beforeedit',
/**
* @event canceledit
* Fired when the editor is cancelled.
* @param {Ext.ux.grid.RowEditor} roweditor This object
* @param {Boolean} forced True if the cancel button is pressed, false is the editor was invalid.
*/
'canceledit',
/**
* @event validateedit
* Fired after a row is edited and passes validation.
* If the listener returns <tt>false</tt> changes to the record will not be set.
* @param {Ext.ux.grid.RowEditor} roweditor This object
* @param {Object} changes Object with changes made to the record.
* @param {Ext.data.Record} r The Record that was edited.
* @param {Number} rowIndex The rowIndex of the row just edited
*/
'validateedit',
/**
* @event afteredit
* Fired after a row is edited and passes validation. This event is fired
* after the store's update event is fired with this edit.
* @param {Ext.ux.grid.RowEditor} roweditor This object
* @param {Object} changes Object with changes made to the record.
* @param {Ext.data.Record} r The Record that was edited.
* @param {Number} rowIndex The rowIndex of the row just edited
*/
'afteredit'
);
},

init: function(grid){
this.grid = grid;
this.ownerCt = grid;
if(this.clicksToEdit === 2){
grid.on('rowdblclick', this.onRowDblClick, this);
}else{
grid.on('rowclick', this.onRowClick, this);
if(Ext.isIE){
grid.on('rowdblclick', this.onRowDblClick, this);
}
}

// stopEditing without saving when a record is removed from Store.
grid.getStore().on('remove', function() {
this.stopEditing(false);
},this);

grid.on({
scope: this,
keydown: this.onGridKey,
columnresize: this.verifyLayout,
columnmove: this.refreshFields,
reconfigure: this.refreshFields,
beforedestroy : this.beforedestroy,
destroy : this.destroy,
bodyscroll: {
buffer: 250,
fn: this.positionButtons
}
});
grid.getColumnModel().on('hiddenchange', this.verifyLayout, this, {delay:1});
grid.getView().on('refresh', this.stopEditing.createDelegate(this, []));
},

beforedestroy: function() {
this.stopMonitoring();
this.grid.getStore().un('remove', this.onStoreRemove, this);
this.stopEditing(false);
Ext.destroy(this.btns, this.tooltip);
},

refreshFields: function(){
this.initFields();
this.verifyLayout();
},

isDirty: function(){
var dirty;
this.items.each(function(f){
if(String(this.values[f.id]) !== String(f.getValue())){
dirty = true;
return false;
}
}, this);
return dirty;
},

startEditing: function(rowIndex, doFocus){
if(this.permisos===true){
if(this.grid.getStore().data.map[this.grid.getSelectionModel().selections.keys].data.permiso['update']===false){
Ext.Msg.alert('Error!', this.permisosText);
return;
}
}
if(this.enEdicion){
this.showTooltip(this.commitChangesText);
return;
}
this.enEdicion=true;
if(Ext.isObject(rowIndex)){
rowIndex = this.grid.getStore().indexOf(rowIndex);
}
if(this.fireEvent('beforeedit', this, rowIndex) !== false){
var g = this.grid, view = g.getView(),
row = view.getRow(rowIndex),
record = g.store.getAt(rowIndex);

this.record = record;
this.rowIndex = rowIndex;
this.values = {};
if(!this.rendered){
this.render(view.getEditorParent());
}
var w = Ext.fly(row).getWidth();
this.setSize(w);
if(!this.initialized){
this.initFields();
}
var cm = g.getColumnModel(), fields = this.items.items, f, val;
for(var i = 0, len = cm.getColumnCount(); i < len; i++){
val = this.preEditValue(record, cm.getDataIndex(i));
f = fields[i];
f.setValue(val);
this.values[f.id] = Ext.isEmpty(val) ? '' : val;
}
this.verifyLayout(true);
if(!this.isVisible()){
this.setPagePosition(Ext.fly(row).getXY());
} else{
this.el.setXY(Ext.fly(row).getXY(), {duration:0.15});
}
if(!this.isVisible()){
this.show().doLayout();
}
if(doFocus !== false){
this.doFocus.defer(this.focusDelay, this);
}
}
},

stopEditing : function(saveChanges){
this.enEdicion = false;
if(!this.isVisible()){
return;
}
if(saveChanges === false || !this.isValid()){
if(this.agregando===true){
this.agregando=false;
this.grid.getStore().removeAt(this.rowIndex);
this.grid.getView().refresh();
}
this.hide();
this.fireEvent('canceledit', this, saveChanges === false);
return;
}
this.agregando=false;
var changes = {},
r = this.record,
hasChange = false,
cm = this.grid.colModel,
fields = this.items.items;
for(var i = 0, len = cm.getColumnCount(); i < len; i++){
if(!cm.isHidden(i)){
var dindex = cm.getDataIndex(i);
if(!Ext.isEmpty(dindex)){
var oldValue = r.data[dindex],
value = this.postEditValue(fields[i].getValue(), oldValue, r, dindex);
if(String(oldValue) !== String(value)){
changes[dindex] = value;
hasChange = true;
}
}
}
}
if(hasChange && this.fireEvent('validateedit', this, changes, r, this.rowIndex) !== false){
r.beginEdit();
Ext.iterate(changes, function(name, value){
r.set(name, value);
});
r.endEdit();
this.fireEvent('afteredit', this, changes, r, this.rowIndex);
}
this.hide();
},

verifyLayout: function(force){
if(this.el && (this.isVisible() || force === true)){
var row = this.grid.getView().getRow(this.rowIndex);
this.setSize(Ext.fly(row).getWidth(), Ext.isIE ? Ext.fly(row).getHeight() + 9 : undefined);
var cm = this.grid.colModel, fields = this.items.items;
for(var i = 0, len = cm.getColumnCount(); i < len; i++){
if(!cm.isHidden(i)){
var adjust = 0;
if(i === (len - 1)){
adjust += 3; // outer padding
} else{
adjust += 1;
}
fields[i].show();
fields[i].setWidth(cm.getColumnWidth(i) - adjust);
} else{
fields[i].hide();
}
}
this.doLayout();
this.positionButtons();
}
},

slideHide : function(){
this.hide();
},

initFields: function(){
var cm = this.grid.getColumnModel(), pm = Ext.layout.ContainerLayout.prototype.parseMargins;
this.removeAll(false);
for(var i = 0, len = cm.getColumnCount(); i < len; i++){
var c = cm.getColumnAt(i),
ed = c.getEditor();
if(!ed){
ed = c.displayEditor || new Ext.form.DisplayField();
}
if(i == 0){
ed.margins = pm('0 1 2 1');
} else if(i == len - 1){
ed.margins = pm('0 0 2 1');
} else{
if (Ext.isIE) {
ed.margins = pm('0 0 2 0');
}
else {
ed.margins = pm('0 1 2 0');
}
}
ed.setWidth(cm.getColumnWidth(i));
ed.column = c;
if(ed.ownerCt !== this){
ed.on('focus', this.ensureVisible, this);
ed.on('specialkey', this.onKey, this);
}
this.insert(i, ed);
}
this.initialized = true;
},

onKey: function(f, e){
if(e.getKey() === e.ENTER){
this.stopEditing(true);
e.stopPropagation();
}
},

onGridKey: function(e){
if(e.getKey() === e.ENTER && !this.isVisible()){
var r = this.grid.getSelectionModel().getSelected();
if(r){
var index = this.grid.store.indexOf(r);
this.startEditing(index);
e.stopPropagation();
}
}
},

ensureVisible: function(editor){
if(this.isVisible()){
this.grid.getView().ensureVisible(this.rowIndex, this.grid.colModel.getIndexById(editor.column.id), true);
}
},

onRowClick: function(g, rowIndex, e){
if(this.clicksToEdit == 'auto'){
var li = this.lastClickIndex;
this.lastClickIndex = rowIndex;
if(li != rowIndex && !this.isVisible()){
return;
}
}
this.startEditing(rowIndex, false);
this.doFocus.defer(this.focusDelay, this, [e.getPoint()]);
},

onRowDblClick: function(g, rowIndex, e){
this.startEditing(rowIndex, false);
this.doFocus.defer(this.focusDelay, this, [e.getPoint()]);
},

onRender: function(){
Ext.ux.grid.RowEditor.superclass.onRender.apply(this, arguments);
this.el.swallowEvent(['keydown', 'keyup', 'keypress']);
this.btns = new Ext.Panel({
baseCls: 'x-plain',
cls: 'x-btns',
elements:'body',
layout: 'table',
width: (this.minButtonWidth * 2) + (this.frameWidth * 2) + (this.buttonPad * 4), // width must be specified for IE
items: [{
ref: 'saveBtn',
itemId: 'saveBtn',
xtype: 'button',
text: this.saveText,
width: this.minButtonWidth,
handler: this.stopEditing.createDelegate(this, [true])
}, {
xtype: 'button',
text: this.cancelText,
width: this.minButtonWidth,
handler: this.stopEditing.createDelegate(this, [false])
}]
});
this.btns.render(this.bwrap);
},

afterRender: function(){
Ext.ux.grid.RowEditor.superclass.afterRender.apply(this, arguments);
this.positionButtons();
if(this.monitorValid){
this.startMonitoring();
}
},

onShow: function(){
if(this.monitorValid){
this.startMonitoring();
}
Ext.ux.grid.RowEditor.superclass.onShow.apply(this, arguments);
},

onHide: function(){
Ext.ux.grid.RowEditor.superclass.onHide.apply(this, arguments);
this.stopMonitoring();
this.grid.getView().focusRow(this.rowIndex);
},

positionButtons: function(){
if(this.btns){
var g = this.grid,
h = this.el.dom.clientHeight,
view = g.getView(),
scroll = view.scroller.dom.scrollLeft,
bw = this.btns.getWidth(),
width = Math.min(g.getWidth(), g.getColumnModel().getTotalWidth());

this.btns.el.shift({left: (width/2)-(bw/2)+scroll, top: h - 2, stopFx: true, duration:0.2});
}
},

// private
preEditValue : function(r, field){
var value = r.data[field];
return this.autoEncode && typeof value === 'string' ? Ext.util.Format.htmlDecode(value) : value;
},

// private
postEditValue : function(value, originalValue, r, field){
return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value;
},

doFocus: function(pt){
if(this.isVisible()){
var index = 0,
cm = this.grid.getColumnModel(),
c;
if(pt){
index = this.getTargetColumnIndex(pt);
}
for(var i = index||0, len = cm.getColumnCount(); i < len; i++){
c = cm.getColumnAt(i);
if(!c.hidden && c.getEditor()){
c.getEditor().focus();
break;
}
}
}
},

getTargetColumnIndex: function(pt){
var grid = this.grid,
v = grid.view,
x = pt.left,
cms = grid.colModel.config,
i = 0,
match = false;
for(var len = cms.length, c; c = cms[i]; i++){
if(!c.hidden){
if(Ext.fly(v.getHeaderCell(i)).getRegion().right >= x){
match = i;
break;
}
}
}
return match;
},

startMonitoring : function(){
if(!this.bound && this.monitorValid){
this.bound = true;
Ext.TaskMgr.start({
run : this.bindHandler,
interval : this.monitorPoll || 200,
scope: this
});
}
},

stopMonitoring : function(){
this.bound = false;
if(this.tooltip){
this.tooltip.hide();
}
},

isValid: function(){
var valid = true;
this.items.each(function(f){
if(!f.isValid(true)){
valid = false;
return false;
}
});
return valid;
},

// private
bindHandler : function(){
if(!this.bound){
return false; // stops binding
}
var valid = this.isValid();
if(!valid && this.errorSummary){
//this.showTooltip(this.getErrorText().join(''));//jg
}
this.btns.saveBtn.setDisabled(!valid);
this.fireEvent('validation', this, valid);
},

lastVisibleColumn : function() {
var i = this.items.getCount() - 1,
c;
for(; i >= 0; i--) {
c = this.items.items[i];
if (!c.hidden) {
return c;
}
}
},

showTooltip: function(msg){
var t = this.tooltip;
if(!t){
t = this.tooltip = new Ext.ToolTip({
maxWidth: 600,
cls: 'errorTip',
width: 300,
title: this.errorText,
autoHide: false,
anchor: 'left',
anchorToTarget: true,
mouseOffset: [40,0]
});
}
var v = this.grid.getView(),
top = parseInt(this.el.dom.style.top, 10),
scroll = v.scroller.dom.scrollTop,
h = this.el.getHeight();
if(top + h >= scroll){
t.initTarget(this.lastVisibleColumn().getEl());
if(!t.rendered){
t.show();
t.hide();
}
t.body.update(msg);
t.doAutoWidth(20);
t.show();
}else if(t.rendered){
t.hide();
}
},

getErrorText: function(){
var data = ['<ul>'];
this.items.each(function(f){
if(!f.isValid(true)){
data.push('<li>',f.getActiveError(),'</li>');
}
});
data.push('</ul>');
return data;
}
});
Ext.preg('roweditor', Ext.ux.grid.RowEditor);



some css, the icons are attached

.x-row-editor-body .x-form-field-wrap is for a fix in the position when it calls Ext.ux.grid.RowEditor's refreshFields(), (bug in RowEditor because when refresh fields it does't apply x-box-item again)


.x-row-editor-body .x-form-field-wrap { position: absolute;} /*fix para row editor*/
.x-tbar-filtro {background-image:url(images/x-tbar-filtro.png);}
.x-tbar-borrarfiltro {background-image:url(images/x-tbar-borrarfiltro.png);}
.x-tbar-agregarfiltro {background-image:url(images/x-tbar-agregarfiltro.png);}
.x-tbar-modificarfiltro {background-image:url(images/x-tbar-modificarfiltro.png);}
.x-tbar-aplicar {background-image:url(images/x-tbar-aplicar.png);}

webtime
16 Nov 2010, 4:58 AM
Hi, a'm interested in using your "filter".... but i've a grid builded with json (configured via metadata).
I'd know if is possible to use your plugin in this scenario???
Thanks for answer!!
Giancarlo

Can you publish a zip with code and icons??? (or icons only??)
Any online sample???