1. #21
    Ext JS Premium Member SMMJ_Dev's Avatar
    Join Date
    Aug 2009
    Location
    St. Louis, MO
    Posts
    88
    Vote Rating
    0
    SMMJ_Dev will become famous soon enough

      0  

    Default


    Very nice! I will definitely work that in. I'm currently anxiously awaiting ExtJS 4.0.7 or ExtJS 4.1 for a new update on the plugin. I will include this.

    Quote Originally Posted by wki01 View Post
    Consider this small improvement

    Code:
    ....
                        width:item.flex||item.width,
                        listeners:{
                            scope:me,
                            change:function(field,newVal,oldVal,eOpts){
                                me.task.delay(me.updateBuffer,function(){
                                    var newFilter={
                                        property: item.dataIndex,
                                        value: field.getSubmitValue()
                                    }, myIndex=-1;
                                    Ext.Array.forEach(
    .....
    So this can work ...

    Code:
    ....
                    filter: {
                      submitFormat: "Ymd",
                        format : 'd/m/Y', 
                        xtype: 'datefield'
                    }
    ....
    thanks
    ExtJS 4.0 - Ext.ux.grid.FooterSummary (Coming Soon)
    ExtJS 4.0 - Ext.ux.form.field.IPhoneSwitch (Coming Soon)
    ExtJS 4.0 - Ext.ux.grid.HeaderFilter
    (Updates Coming Soon)
    ExtJS 4.0 - Ext.ux.menu.DynamicMenu

    ExtJS 4.0 - Ext.ux.form.field.ClearableCombo
    ExtJS 4.0 - Ext.ux.form.field.FormPanelEditor
    ExtJS 4.0 - Grouping Extra Features (Overrides) (Updates Coming Soon)

  2. #22
    Sencha User
    Join Date
    Jun 2010
    Location
    Buenos Aires, Argentina
    Posts
    213
    Vote Rating
    9
    ldonofrio will become famous soon enough

      0  

    Default


    Thanks for this SMMJ.

    If you set width and not flex to the column, the initial layout is broken, you can fix this listening to render not afterrender on grid.

    I'm working on features like, show/hide filters, i'll post the updated code here.

    Regards

    Leonardo

  3. #23
    Sencha User
    Join Date
    Jun 2010
    Location
    Buenos Aires, Argentina
    Posts
    213
    Vote Rating
    9
    ldonofrio will become famous soon enough

      0  

    Default


    I've updated your code to support renderHidden, isVisible(), setVisible(), and have fixed some bugs, expecially i've fixed the filter bug that you wrote before.

    I'll keep adding features to this plugin. Thanks again.

    Here is the code.......
    PHP Code:
    /**
     * Plugin that enable filters on the grid header.<br>
     * The header filters are integrated with new Ext4 <code>Ext.data.Store</code> filters.<br>
     *
     * @author SMMJ_Dev
     * @version unversioned preview release
     * @updated 2011-10-18 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
     * Support renderHidden config option, isVisible(), and setVisible() methods (added getHeaderFilter() method to the grid)
     * Fix filter bug that append filters to Store filters MixedCollection
     * Fix layout broken on initial render when columns have width property
     */

    Ext.define('Ext.ux.grid.HeaderFilter', {
        
    extend'Ext.util.Observable',
        
    alias'plugin.hfilter',
        
    uses: [
            
    'Ext.container.Container',
            
    'Ext.util.DelayedTask'
        
    ],
        
    updateBuffer500,
        
        
    renderHiddenfalse,

        
    taskExt.create('Ext.util.DelayedTask'),

        
    init: function(grid) {
            var 
    me this;
            
            
    me.filterArray = [];
            
            
    grid.on({
                
    scopeme,
                
    renderme.onGridRender,
                
    columnresizeme.onGridColumnResize,
                
    columnhideme.onGridColumnHide,
                
    columnshowme.onGridColumnShow,
                
    columnmoveme.onGridColumnMove
            
    });
            
    grid.addEvents('filterupdated');
            
            
    Ext.apply(grid, {
                
    headerFilterthis,
                
    getHeaderFilter: function() {
                    return 
    this.headerFilter;
                }
            });
            
            
    me.grid grid;
            
    me.container null;
        },
        
        
    isVisible: function() {
            return 
    this.container.isVisible();
        },
        
        
    setVisible: function(visible) {
            
    this.container.setVisible(visible);
            
    this.grid.headerCt.doLayout();
        },
        
        
    onGridColumnHide: function(headerCt,col) {
            var 
    filter Ext.getCmp(col.id "-filter");
            if(
    filter) { filter.hide(); }
        },

        
    onGridColumnShow:function(headerCtcol) {
            var 
    filter Ext.getCmp(col.id "-filter");
            if(
    filter) { filter.show(); }
        },

        
    onGridColumnResize: function(headerCtcolwidth) {
            var 
    filter Ext.getCmp(col.id "-filter");
            if(
    filter) { filter.setWidth(width); }
        },

        
    onGridColumnMove: function(headerCtcolfromIdxtoIdx) {
            var 
    hFilter headerCt.up('gridpanel').getDockedItems("#headerFilter")[0];
            
    hFilter.move(fromIdxtoIdx);
        },

        
    onGridRender: function(gridobj){
            var 
    me this;
            
    me.container Ext.create('Ext.container.Container', {
                
    dock'top',
                
    id'headerFilter',
                
    componentClsExt.baseCSSPrefix 'grid-hfilter',
                
    weight101,
                
    height22,
                
    layout'hbox',
                
    hiddenme.renderHidden
            
    });
            
    Ext.each(grid.headerCt.items.items, function(item) {
                
    item Ext.getCmp(item.id);
                if(!
    item.filter) {
                    var 
    col Ext.create('Ext.container.Container', {
                        
    layout'fit',
                        
    componentClsExt.baseCSSPrefix 'column-no-filter',
                        
    heightme.container.height,
                        
    iditem.id "-filter",
                        
    hiddenitem.hidden,
                        
    widthitem.flex || item.width
                    
    });
                } else {
                    var 
    col item.filter;
                    
    Ext.apply(col, {
                        
    layout'fit',
                        
    componentClsExt.baseCSSPrefix 'column-filter',
                        
    id:item.id "-filter",
                        
    hiddenitem.hidden,
                        
    widthitem.flex || item.width,
                        
    listeners: {
                            
    scopeme,
                            
    change: function(fieldnewValoldValeOpts) {
                                
    me.task.delay(me.updateBuffer, function() {
                                    var 
    newFilter = {
                                        
    propertyitem.dataIndex,
                                        
    valuenewVal,
                                        
    headerIditem.id
                                    
    };
                                    var 
    myIndex = -1;
                                    
    Ext.Array.forEach(me.filterArray, function(item2indexallItems) {
                                        if(
    item2.property === item.dataIndex) {
                                            
    myIndex index;
                                        }
                                    }, 
    this);
                                    if(
    myIndex != -1) {
                                        
    me.filterArray.splice(myIndex1);
                                    }
                                    if(
    newVal) {
                                        
    me.filterArray.push(newFilter);
                                        if(!
    item.getEl().hasCls(Ext.baseCSSPrefix 'column-filtered')) {
                                            
    item.getEl().addCls(Ext.baseCSSPrefix 'column-filtered');
                                        }
                                    } else {
                                        if(
    item.getEl().hasCls(Ext.baseCSSPrefix 'column-filtered')) {
                                            
    item.getEl().removeCls(Ext.baseCSSPrefix 'column-filtered');
                                        }
                                    }
                                    if(
    me.filterArray.length 0) {
                                        
    grid.store.filters.clear();
                                        
    grid.store.filter(me.filterArray);
                                    } else {
                                        
    grid.store.clearFilter();
                                    }
                                    
    me.fireEvent('filterupdated'me.filterArraynewValoldVal);
                                });
                            }
                        }
                    });
                }
                
    me.container.add(col);
            });
            
    grid.dockedItems.add(me.container);
        }
    }); 
    Quote Originally Posted by SMMJ_Dev View Post
    Thanks drplasma,

    There are currently alot of bugs I still need to work out.

    One big issue is that if I filter for "abcdf" instead of "abcde" and only "abcde" exists, then I will get nothing back. Then if I press backspace to filter for "abcd" the filter is applying the filter to an already empty set of data. So if filter is called when you are not finished typing and it is an incorrect value it will not show anything once you are finished typing in the filter.
    I am calling the standard filter function on the store. The store does not correctly interpret the filter of 09 for the date. It looks like it only understands the full date for a valid date filter. For example if you paste in "09/28/1981" then the store is filtered correctly. Once I get some time, I will work out the errors.

  4. #24
    Ext JS Premium Member
    Join Date
    Nov 2008
    Posts
    293
    Vote Rating
    3
    wki01 is on a distinguished road

      0  

    Default


    Even a small improvement:
    So this works
    Code:
    ...
                filter: {
                    xtype:'textfield',
                    hidden: (App.anag.role === "AG")
                }
    Code:
    ...
            Ext.each(grid.headerCt.items.items,function(item){
                item=Ext.getCmp(item.id);
                if(!item.filter || item.filter.hidden === true){
                    var col=Ext.create("Ext.container.Container",{
    thanks

  5. #25
    Ext JS Premium Member
    Join Date
    Nov 2008
    Posts
    293
    Vote Rating
    3
    wki01 is on a distinguished road

      0  

    Default


    There are some problems with version 4.07 + with filters combo type + IE9.
    Is not properly heard the "me.task.delay" function
    I suspect it's a bug in the new version.
    thanks

  6. #26
    Sencha User
    Join Date
    Jun 2010
    Location
    Buenos Aires, Argentina
    Posts
    213
    Vote Rating
    9
    ldonofrio will become famous soon enough

      0  

    Default


    I've updated this code again.
    Rendering code rewrited (read comments inside the file).
    Support showClearButton config option, shows a button to clear the field for each column.
    I'll keep adding features to this plugin.

    Tested on IE9, FF7, Chrome14 ---- Ext4.0.2a (i'll test on 407 later)

    Code:
    PHP Code:
    /**
     * Plugin that enable filters on the grid header.<br>
     * The header filters are integrated with new Ext4 <code>Ext.data.Store</code> filters.<br>
     *
     * @author SMMJ_Dev
     * @version unversioned preview release
     * @updated 2011-10-18 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
     * Support renderHidden config option, isVisible(), and setVisible() methods (added getHeaderFilter() method to the grid)
     * Fix filter bug that append filters to Store filters MixedCollection
     * Fix layout broken on initial render when columns have width property
     * @updated 2011-10-21 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
     * Rendering code rewrited, filters are now rendered inside de column headers, this solves scrollable grids issues, now scroll, columnMove, and columnHide/Show is handled by the headerCt
     * Support showClearButton config option, render a clear Button for each filter to clear the applied filter (iconCls and tooltip configurable)
     */

    Ext.define('Ext.ux.grid.HeaderFilter', {
        
    extend'Ext.util.Observable',
        
    alias'plugin.hfilter',
        
    uses: [
            
    'Ext.container.Container',
            
    'Ext.util.DelayedTask',
            
    'Ext.button.Button',
            
    'Ext.layout.container.HBox'
        
    ],
        
    updateBuffer            500,

        
    renderHidden             false,

        
    showClearButton            true,
        
    clearButtonIconCls        'clear',
        
    clearButtonTooltip        'Clear this filter...',

        
    init: function(grid) {
            var 
    me this;

            
    grid.on({
                
    scopeme,
                
    afterrenderme.onGridRender,
                
    columnresizeme.onGridColumnResize
            
    });
            
    grid.addEvents('filterupdated');

            
    Ext.apply(grid, {
                
    headerFilterthis,
                
    getHeaderFilter: function() {
                    return 
    this.headerFilter;
                }
            });

            
    me.grid grid;
            
    me.task Ext.create('Ext.util.DelayedTask');
            
    me.filterArray = [];
            
    me.visible true;
            
    me.containers null;
            
    me.containersHeight null;
        },

        
    onGridColumnResize: function(headerCtcolwidth) {
            var 
    me this;
            if(!
    me.containers) return;
            if (
    me.containers[col.id] && me.containers[col.id].rendered) {
                
    me.containers[col.id].setWidth(width);
                
    me.containers[col.id].doLayout();
            }
        },

        
    onGridRender: function(grid) {
            var 
    me this;
            
    me.containers = {};
            
            var 
    columns grid.headerCt.getGridColumns(true);
            
    Ext.each(columns, function(column) {
                if(
    column.filter) {
                    var 
    filterContainer Ext.create('Ext.container.Container', {
                        
    layout'hbox',
                        
    bodyStyle'background-color: "transparent"',
                        
    widthcolumn.getWidth(),
                        
    padding: (me.showClearButton '0 1 0 0' 0),
                        
    listeners: {
                            
    scopeme,
                            
    element'el',
                            
    mousedown: function(e) { e.stopPropagation(); },
                            
    click: function(e) { e.stopPropagation(); },
                            
    keydown: function(e) { e.stopPropagation(); },
                            
    keypress: function(e) { e.stopPropagation(); },
                            
    keyup: function(e) { e.stopPropagation(); }
                        },
                        
    items: [Ext.apply(column.filter, {
                            
    flex1,
                            
    columncolumn,
                            
    margin0,
                            
    listeners: {
                                
    scopeme,
                                
    changeme.applyFilters
                            
    }
                        })]
                    });
                    if (
    me.showClearButton) {
                        
    filterContainer.add({
                            
    xtype'button',
                            
    ui'default-toolbar',
                            
    margin0,
                            
    padding2,
                            
    style'text-align: center;',
                            
    iconClsme.clearButtonIconCls,
                            
    tooltipme.clearButtonTooltip,
                            
    handler: function(btn) {
                                
    btn.previousSibling().reset();
                            }
                        });
                    }
                    
    filterContainer.on('afterrender', function(container) {
                        var 
    me this;
                        if (
    me.containersHeight) return;
                        
    me.containersHeight container.getHeight();
                        if (
    me.renderHidden) {
                            
    me.grid.headerCt.doLayout();
                            
    me.setVisible(false);
                        }
                    }, 
    me, { singletrue });
                    
    filterContainer.render(column.el);
                    
    this.containers[column.id] = filterContainer;
                    
    column.setPadding Ext.Function.createInterceptor(column.setPadding, function(h) { return false; });
                }
            }, 
    me);
        },
        
        
    isVisible: function() {
            var 
    me this;
            return 
    me.visible;
        },

        
    setVisible: function(visible) {
            var 
    me this;
            if (!
    me.containersHeight) return;
            if (
    me.visible == visible ) return;
            var 
    headerCt me.grid.headerCt;
            
    me.visible visible;
            
    headerCt.setHeight((visible headerCt.getHeight() + me.containersHeight headerCt.getHeight() - me.containersHeight))
            
    headerCt.doLayout();
        },

        
    applyFilters: function(fieldnewValoldValeOpts) {
            var 
    me this;
            var 
    grid this.grid;
            var 
    column field.column;
            
    me.task.delay(me.updateBuffer, function() {
                var 
    newFilter = {
                    
    propertycolumn.dataIndex,
                    
    valuenewVal,
                    
    headerIdcolumn.id
                
    };
                var 
    myIndex = -1;
                
    Ext.each(me.filterArray, function(item2indexallItems) {
                    if(
    item2.property === column.dataIndex) {
                        
    myIndex index;
                    }
                });
                if(
    myIndex != -1) {
                    
    me.filterArray.splice(myIndex1);
                }
                if(
    newVal) {
                    
    me.filterArray.push(newFilter);
                    if(!
    column.getEl().hasCls(Ext.baseCSSPrefix 'column-filtered')) {
                        
    column.getEl().addCls(Ext.baseCSSPrefix 'column-filtered');
                    }
                } else {
                    if(
    column.getEl().hasCls(Ext.baseCSSPrefix 'column-filtered')) {
                        
    column.getEl().removeCls(Ext.baseCSSPrefix 'column-filtered');
                    }
                }
                if(
    me.filterArray.length 0) {
                    
    grid.store.filters.clear();
                    
    grid.store.filter(me.filterArray);
                } else {
                    
    grid.store.clearFilter();
                }
                
    me.fireEvent('filterupdated'me.filterArraynewValoldVal);
            }, 
    me);
        }
    }); 

  7. #27
    Ext JS Premium Member
    Join Date
    Mar 2008
    Location
    Phoenix, AZ
    Posts
    628
    Vote Rating
    10
    zombeerose will become famous soon enough zombeerose will become famous soon enough

      0  

    Default


    A few ideas...

    1) Would it be possible for you to support fuzzy/wildcard filters? Some example data:
    11/13/1952
    12/01/1948
    03/15/1952
    If I type "1952", I would like to see two records.

    2) What if you auto-create a filter based on the 'editor' config of a column to avoid redefining a lot of the same properties?

    3) Any chance you will add an option into the column menu to enable/disable the filter row altogether? Similar to how you can enable/disable grouping.

    Thanks for the plugin

  8. #28
    Sencha User
    Join Date
    Jun 2010
    Location
    Buenos Aires, Argentina
    Posts
    213
    Vote Rating
    9
    ldonofrio will become famous soon enough

      0  

    Default


    1) I don't need that, you can implement it.
    2) This plugin doesn't care about if the grid is editable or not
    3) It exists, see setVisible method, put a button in your toptoolbar or paging and toggle visible status, also supports renderHidden: true, that is what i use.

    Regards

    Quote Originally Posted by zombeerose View Post
    A few ideas...

    1) Would it be possible for you to support fuzzy/wildcard filters? Some example data:
    11/13/1952
    12/01/1948
    03/15/1952
    If I type "1952", I would like to see two records.

    2) What if you auto-create a filter based on the 'editor' config of a column to avoid redefining a lot of the same properties?

    3) Any chance you will add an option into the column menu to enable/disable the filter row altogether? Similar to how you can enable/disable grouping.

    Thanks for the plugin

  9. #29
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,112
    Vote Rating
    470
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      0  

    Default


    I've updated this code again.
    Rendering code rewrited (read comments inside the file).
    Some comments:
    Width need to have allowances for flex columns
    ugly fix:
    Code:
    width:(column.flex === 1) ? 2000 : column.getWidth()
    Would like to have the buttons inside the editor with the clear button active on hover. It looks a bad to have the editor displayed minus the button, then a button is displayed on hover next to editor.
    same idea as:
    http://www.eekboom.de/ClearButton.html
    http://www.sencha-addons.com/public/...les/index.html


    I like/purchased GMS for ExtJS3, but Saki simply quit responding to emails.

    Filter does not fire if you delete a character, then hit enter. You have to clear filter and start again,

    Global clear button for all. (as seen in GMS)

    Regards,
    Scott.

  10. #30
    Sencha User
    Join Date
    Jun 2010
    Location
    Buenos Aires, Argentina
    Posts
    213
    Vote Rating
    9
    ldonofrio will become famous soon enough

      0  

    Default


    1) Can't reproduce, sizing is handled by the onGridColumnResize listener, independently of what is passed in the container's width.
    2) Love it, i'll add this today
    3) Can't reproduce, i'm using remoteFilter and filters are ok. Remote or Local Filter? Browser? Ext versiĆ³n?
    4) Will add clearFilters public method, i'm not sure about including this en the grid, users can call the method in a tollbar handler or whatever.

    Thanks..

    Leonardo

    Quote Originally Posted by scottmartin View Post
    Some comments:
    Regards,
    Scott.