PDA

View Full Version : Grid store filtering while highlighting cell



ajsushil
21 May 2013, 4:49 AM
Here's some context before I dive into the problem:

We have a webpage where there is a Single ExtJs grid, the grid is editable,(cellEditing plugin) and changed data can be saved / persisted.
There is also a Find and replace feature on the same grid, by using which the user can directly search a particular string, highlight the matches and replace a matched cell wi4390543905th a different value.

Here is a screen shot :




The design to implement Find & Replace feature is:
While the user types a value in the find text-box, (in this case "AMR"), the store of the grid is filtered and the coordinates of the filtered cells {row index, column name}, are stored in a an array in global scope so that when user clicks on the next/previous button, the array can be looped through to get the coordinates of the desired cell to be highlighted, then get the DOM of the cell concerned and add a class to highlight the cell.

The logic to get the coordinates of the matched records :


searchGrid:function(Text,e){
var controller=this;
$('.highlightMatch').removeClass('highlightMatch');
var findVal=Ext.getCmp('find').getValue();<-----------------------Get the input by the user
var matchedRecords=[];
var grid=Ext.getCmp('dataGridViewId');
console.log(grid,"Records in store right now:",grid.getStore());
grid.getStore().each(function(record){
$.each(appLocalStore.data.get('columnMetadata'),function(){

if(null!=record.raw[this.columnName] && null!=record.raw[this.columnName].toLowerCase()){
var n=record.raw[this.columnName].toLowerCase().indexOf(findVal.toLowerCase());
if(n!=-1){
matchedRecords.push({<-----------------------Add matched record index and column name in an array
field:this.columnName,
rowIndex:record.index
});
}
}

});
});
appLocalStore.data.set('matchedRecords',matchedRecords);<-----------------------Set the record in global scope

var cursorPosition={<-----------------------Set the cursor position to start
index:-1,
direction:'start'
};
appLocalStore.data.set('cursorPosition',cursorPosition);
}


While clicking on the next button, the logic is :


findNext:function(){
var controller=this;
var findVal=Ext.getCmp('find').getValue();
var matchs=appLocalStore.data.get('matchedRecords');<--------------------------Get the coordinates of matched record from global scope
if(findVal!==''){
var cursorPosition=appLocalStore.data.get('cursorPosition');<-----------------------Get the current index of the record where match is found
var cols=Ext.getCmp('dataGridViewId').getView().getGridColumns();
//to unhighlight last match
$('.highlightMatch').removeClass('highlightMatch');

if(cursorPosition.index<0 || cursorPosition.index==appLocalStore.data.get('matchedRecords').length-1){
cursorPosition.index=0;
}else{
cursorPosition.index=cursorPosition.index+1;
}

//to highlight current match
var recordToHighlight=appLocalStore.data.get('matchedRecords')[cursorPosition.index];<---------Get the coordinates of the next record to be highlighted
var currentMatchedRecord=Ext.getCmp('dataGridViewId').getStore().getAt(recordToHighlight.rowIndex);<---------Get the matched record from the store
var column;
var cell;
$.each(cols,function(index){
if(this.dataIndex===recordToHighlight.field){
column=this;
}
});
cell=Ext.getCmp('dataGridViewId').getView().getCell(currentMatchedRecord,column);<--------------Get the DOM of matched cell of the record

cell.addCls('highlightMatch');<---------------------------------------------Get the DOM of matched cell of the record

cursorPosition.direction='forward';
appLocalStore.data.set('cursorPosition',cursorPosition);

//adjust scroll position<---------------------------------------------Set scroll position of the highlighted cell to the middle of the grid
var c2 = $('#dataGridViewId .x-grid-view');
var row=Ext.getCmp('dataGridViewId').getView().getNode(currentMatchedRecord);
var top=0;
if((row.offsetTop-40)<0){
top=0;
}else{
top=row.offsetTop-40;
}
$(c2[1]).scrollTop(top);
$(c2[1]).scrollLeft((cell.dom.offsetLeft)/2);
}
}

And here is the problem:

The matches are done against all the records that are there in the store, but in the browser, the grid structure doesn’t have all the records in the DOM, extJs dynamically appends DOM of records in the grid as and when scrolling is done.
And if a record is not yet present in the Dom and an attempt is made to get the cell of that record from the dom(cell=Ext.getCmp('dataGridViewId').getView().getCell(currentMatchedRecord,column); ), it throws an error and the functionality breaks.
43905

So what we need here is to know the indices of the records in the store, which are the in the DOM, so that we can restrict the find next functionality not look beyond the range of indices after which records are not there in the DOM.

Please let me know if I am not clear enough while explaining the issue.

slemmon
23 May 2013, 8:08 AM
I'm not seeing a public method to get the loaded range, but you might look at bufferedRenderer's getViewRange (http://docs.sencha.com/extjs/4.2.0/#!/api/Ext.grid.plugin.BufferedRenderer-method-getViewRange)() method to get some ideas.