1. #1
    Sencha User
    Join Date
    Oct 2011
    Posts
    5
    Vote Rating
    0
    baseliners is on a distinguished road

      0  

    Default Filtering via LiveSearch in grid?

    Filtering via LiveSearch in grid?


    Has anyone figured out a way to have the live search on a grid be a filter for grid content instead of highlighting the search term? Highlighting isn't helpful when there are lots of rows and you need to scroll a lot to find what you're looking for.. thanks!

  2. #2
    Sencha User juanb's Avatar
    Join Date
    Jun 2011
    Location
    usa
    Posts
    42
    Vote Rating
    1
    juanb is on a distinguished road

      1  

    Default


    yes i have developed that component (roghly)
    The component:
    Code:
     /*
    
    This file is part of Ext JS 4
    
    Copyright (c) 2011 Sencha Inc
    
    Contact:  http://www.sencha.com/contact
    
    Commercial Usage
    Licensees holding valid commercial licenses may use this file in accordance with the Commercial Software License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Sencha.
    
    If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
    
     */
    /**
     * @class Ext.ux.LiveFilterGridPanel
     * @extends Ext.grid.Panel
     * <p>A GridPanel class with live search support.</p>
     * @author Nicolas Ferrero & Juan Borda
     */
    Ext.define('Ext.ux.LiveFilterGridPanel', {
        extend: 'Ext.grid.Panel',
        requires: [
        'Ext.toolbar.TextItem',
        'Ext.form.field.Checkbox',
        'Ext.form.field.Text',
        'Ext.ux.statusbar.StatusBar'
        ],
        
        /**
         * @private
         * search value initialization
         */
        searchValue: null,
        
        /**
         * @private
         * The row indexes where matching strings are found. (used by previous and next buttons)
         */
        indexes: [],
        
        /**
         * @private
         * The row index of the first search, it could change if next or previous buttons are used.
         */
        currentIndex: null,
        
        /**
         * @private
         * The generated regular expression used for searching.
         */
        searchRegExp: null,
        
        /**
         * @private
         * Case sensitive mode.
         */
        caseSensitive: false,
        
        /**
         * @private
         * Regular expression mode.
         */
        regExpMode: false,
        
        /**
         * @cfg {String} matchCls
         * The matched string css classe.
         */
        matchCls: 'x-livesearch-match',
        
        defaultStatusText: 'Nothing Found',
        
        // Component initialization override: adds the top and bottom toolbars and setup headers renderer.
        initComponent: function() {
            var me = this;
            me.tbar = [me.indexes.join(',')+':',{
                xtype: 'textfield',
                name: 'searchField',
                hideLabel: true,
                width: 200
            }
            ,{
                xtype: 'button', 
                text: 'Filter',
                handler: me.onTextFieldChange,
                icon:base_url+'jscript/ext/src/ux/filter/filter.gif',
                scope: me
            }
            ,{
                xtype: 'button', 
                text: 'Clear Filter',
                icon:base_url+'jscript/ext/src/ux/filter/filter_delete.gif',
                handler: function(){
                    me.store.clearFilter();
                },
                scope: me
            }
            ];
    
            me.bbar = Ext.create('Ext.ux.StatusBar', {
                defaultText: me.defaultStatusText,
                name: 'searchStatusBar'
            });
            
            me.callParent(arguments);
        },
        
        // afterRender override: it adds textfield and statusbar reference and start monitoring keydown events in textfield input 
        afterRender: function() {
            var me = this;
            me.callParent(arguments);
            me.textField = me.down('textfield[name=searchField]');
            me.statusBar = me.down('statusbar[name=searchStatusBar]');
        },
        // detects html tag
        tagsRe: /<[^>]*>/gm,
        
        // DEL ASCII code
        tagsProtect: '\x0f',
        
        // detects regexp reserved word
        regExpProtect: /\\|\/|\+|\\|\.|\[|\]|\{|\}|\?|\$|\*|\^|\|/gm,
        
        /**
     * In normal mode it returns the value with protected regexp characters.
     * In regular expression mode it returns the raw value except if the regexp is invalid.
     * @return {String} The value to process or null if the textfield value is blank or invalid.
     * @private
     */
        getSearchValue: function() {
            var me = this,
            value = me.textField.getValue();
                
            if (value === '') {
                return null;
            }
            if (!me.regExpMode) {
                value = value.replace(me.regExpProtect, function(m) {
                    return '\\' + m;
                });
            } else {
                try {
                    new RegExp(value);
                } catch (error) {
                    me.statusBar.setStatus({
                        text: error.message,
                        iconCls: 'x-status-error'
                    });
                    return null;
                }
                // this is stupid
                if (value === '^' || value === '$') {
                    return null;
                }
            }
            
            var length = value.length,
            resultArray = [me.tagsProtect + '*'],
            i = 0,
            c;
                
            for(; i < length; i++) {
                c = value.charAt(i);
                resultArray.push(c);
                if (c !== '\\') {
                    resultArray.push(me.tagsProtect + '*');
                } 
            }
            return resultArray.join('');
        },
        
        /**
     * Finds all strings that matches the searched value in each grid cells.
     * @private
     */
        onTextFieldChange: function() {
            var me = this,
            count = 0;
    
            me.view.refresh();
            // reset the statusbar
            me.statusBar.setStatus({
                text: me.defaultStatusText,
                iconCls: ''
            });
    
            me.searchValue = me.getSearchValue();
             
            //me.indexes = [];
            var indexes=me.indexes;
            me.currentIndex = null;
            //---clear previous filter
            me.store.clearFilter();
            if (me.searchValue !== null) {
                me.searchRegExp = new RegExp(me.searchValue, 'g' + (me.caseSensitive ? '' : 'i'));
                var regexp=me.searchRegExp;
                //console.log(me.index,me.searchRegExp);
                me.store.filterBy(
                    function(obj){
                        var test=false;
                        //console.log(obj,indexes);
                        for(idx in indexes){
                            index=indexes[idx];
                            test=test || regexp.test(obj.data[index]);
                        //console.log('testing',index,obj.data[index],regexp.toString(),test);
                        }
                        
                        //console.log('Result:',test);
                        return test;
                    });
                //me.store.filter(me.index,me.searchRegExp);
                // results found
                me.statusBar.setStatus({
                    text: me.store.count() + ' matche(s) found.',
                    iconCls: 'x-status-valid'
                });
                        }
    
            // no results found
            if (me.currentIndex === null) {
                me.getSelectionModel().deselectAll();
            }
    
            // force textfield focus
            me.textField.focus();
        },
           
     /**
     * Switch to case sensitive mode.
     * @private
     */    
        caseSensitiveToggle: function(checkbox, checked) {
            this.caseSensitive = checked;
            this.onTextFieldChange();
        },
        
        /**
     * Switch to regular expression mode
     * @private
     */
        regExpToggle: function(checkbox, checked) {
            this.regExpMode = checked;
            this.onTextFieldChange();
        }
    });
    usage (use indexes to tell wich columns to filter on):
    Code:
    var othergrid=Ext.create('Ext.ux.LiveFilterGridPanel',{
        //title:'All Similar Frames Available',
        columnLines: true,
        stripeRows       : true,
        id:'otherGrid',
        indexes:['title','idframe'],
    .....
    .....

  3. #3
    Sencha User
    Join Date
    Oct 2011
    Posts
    5
    Vote Rating
    0
    baseliners is on a distinguished road

      0  

    Default


    This is great! Thanks a lot for posting. A few questions (based on testing on Chrome 15 beta on OS X 10.7.1 with ExtJS 4.0.2):

    - the search isn't "live", i.e. the filtering doesn't happen until the Filter button is clicked.. are you thinking of making it live? Or maybe allowing for the keyboard return/enter to kick off the filter..
    - when Clear Filter is clicked, would it make sense to also clear the search text in the input box?

    Also, I see some code for regex handling but the Regular Expression checkbox is not present.. guessing that's work in progress.. and I got an error about base_url not being defined so had to comment out those icon definition lines...

    Thanks again for your work on this, it's very useful!

  4. #4
    Sencha User juanb's Avatar
    Join Date
    Jun 2011
    Location
    usa
    Posts
    42
    Vote Rating
    1
    juanb is on a distinguished road

      0  

    Wink


    You can easily add the type & filter feature replacing in the searchField code by:
    Code:
    {
                xtype: 'textfield',
                name: 'searchField',
                hideLabel: true,
                width: 200,
                listeners: {
                         change: {
                             fn: me.onTextFieldChange,
                             scope: this,
                             buffer: 100
                         }
                     }
            }

  5. #5
    Sencha User
    Join Date
    Oct 2011
    Posts
    5
    Vote Rating
    0
    baseliners is on a distinguished road

      0  

    Default


    That's great! Thanks for posting. I have a grid with about 7000 rows and it looks like with the code above, the search starts as soon as I type the first character.. is there a quick way to delay the start of the search to be <last_key_input> + <short_lag>? Thanks!

  6. #6
    Sencha User juanb's Avatar
    Join Date
    Jun 2011
    Location
    usa
    Posts
    42
    Vote Rating
    1
    juanb is on a distinguished road

      0  

    Default


    that's why I disabled this feature, you can have a delay associated with the keypress but you will not always want that. I'm thinking in a function that resets a counter on each keypress if you stop pressing keys then it's ok to apply the filter.
    Also the timer has to be initialized on the first keypress and stoped when the filter is applied.

    You can replace the function called on key press at the line:
    Code:
    fn: me.onTextFieldChange,
    and make a call to your time control function

  7. #7
    Touch Premium Member
    Join Date
    Sep 2011
    Posts
    69
    Vote Rating
    2
    pdm is on a distinguished road

      0  

    Default


    You may just want to filter the grid:

    Code:
    onTextfieldChange: function(field, newValue, oldValue, options) {
        var grid = field.up('gridpanel');
        grid.store.clearFilter();
        grid.store.load().filter([
            {id: 'name', property: "name", value: newValue, anyMatch: true}
        ]);
    }
    Although this only searches the 'name' field in this case.

Thread Participants: 2

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi