GridPanel 为列提供“仅显示空白” 的支持

(function () {

    // ============================================================
    // 安装函数
    //
    // 使用:
    //
    // installBlankFilter(Ext.getCmp('gcDay'));
    //
    // 其它 Grid:
    //
    // installBlankFilter(Ext.getCmp('其它GridID'));
    //
    // ============================================================

    function installBlankFilter(grid) {

        if (!grid) {
            return;
        }


        var view = grid.getView();

        if (!view) {
            return;
        }


        var headerCt = view.headerCt;

        if (!headerCt) {
            return;
        }


        var menu = headerCt.getMenu();

        if (!menu) {
            return;
        }


        // ========================================================
        // 防止同一个 Grid 重复安装
        // ========================================================

        if (grid.__blankFilterInstalled) {
            return;
        }

        grid.__blankFilterInstalled = true;


        // ========================================================
        // 当前菜单正在操作的列
        // ========================================================

        var currentColumn = null;


        // ========================================================
        // FilterHeader 高亮颜色
        // ========================================================

        var BLANK_FILTER_COLOR = '#ffe6e6';


        // ========================================================
        // 保存“仅显示空白”的状态
        //
        // 不依赖 Store Filters。
        //
        // ========================================================

        var blankFilterState = {};


        // ========================================================
        // 防止恢复 Filter 时递归触发 filterchange
        // ========================================================

        var restoringBlankFilters = false;


        // ========================================================
        // 防止 clearFilter 包装函数递归
        // ========================================================

        var clearingAllFilters = false;


        // ========================================================
        // 获取当前 Grid 中的 FilterHeader TextField
        //
        // 查询范围限定为当前 Grid。
        // ========================================================

        function getFilterHeaderFields() {

            return Ext.ComponentQuery.query(
                'textfield',
                grid
            );

        }


        // ========================================================
        // 获取当前 Grid 所有 Column
        // ========================================================

        function getColumns() {

            var columns = [];


            headerCt.items.each(

                function (column) {

                    if (
                        column &&
                        column.dataIndex
                    ) {

                        columns.push(
                            column
                        );

                    }

                }
            );


            return columns;
        }


        // ========================================================
        // 根据 dataIndex 找 FilterHeader TextField
        // ========================================================

        function getFilterHeaderField(dataIndex) {

            var fields =
                getFilterHeaderFields();


            if (
                !fields ||
                !fields.length
            ) {
                return null;
            }


            var columns =
                getColumns();


            var columnIndex = -1;


            for (
                var i = 0;
                i < columns.length;
                i++
            ) {

                if (
                    columns[i].dataIndex ===
                    dataIndex
                ) {

                    columnIndex = i;

                    break;
                }

            }


            if (columnIndex < 0) {
                return null;
            }


            return fields[columnIndex] || null;
        }


        // ========================================================
        // 设置 FilterHeader 背景色
        // ========================================================

        function setFilterHeaderColor(
            dataIndex,
            enabled
        ) {

            var field =
                getFilterHeaderField(
                    dataIndex
                );


            if (!field) {
                return;
            }


            if (enabled) {

                field.setFieldStyle({

                    'background-color':
                        BLANK_FILTER_COLOR,

                    'background-image':
                        'none'

                });

            } else {

                field.setFieldStyle({

                    'background-color':
                        '',

                    'background-image':
                        ''

                });

            }

        }


        // ========================================================
        // 获取空白 Filter ID
        // ========================================================

        function getFilterId(dataIndex) {

            return (
                '__blank_filter_' +
                dataIndex
            );

        }


        // ========================================================
        // 判断 Boolean 字段
        // ========================================================

        function isBooleanField(dataIndex) {

            var store =
                grid.getStore();


            if (!store) {
                return false;
            }


            var model =
                store.getModel();


            if (!model) {
                return false;
            }


            var field =
                model.getField(
                    dataIndex
                );


            return (
                field &&
                field.type === 'boolean'
            );
        }


        // ========================================================
        // 创建空白 Filter
        // ========================================================

        function createBlankFilter(dataIndex) {

            return new Ext.util.Filter({

                id:
                    getFilterId(
                        dataIndex
                    ),


                filterFn:
                    function (record) {

                        var value =
                            record.get(
                                dataIndex
                            );


                        return (

                            value === null ||

                            typeof value ===
                                'undefined' ||

                            value === '' ||

                            (
                                typeof value ===
                                    'string' &&

                                Ext.String.trim(
                                    value
                                ) === ''
                            )

                        );

                    }

            });
        }


        // ========================================================
        // 恢复所有“仅显示空白” Filter
        // ========================================================

        function restoreBlankFilters() {

            if (restoringBlankFilters) {
                return;
            }


            if (clearingAllFilters) {
                return;
            }


            var store =
                grid.getStore();


            if (!store) {
                return;
            }


            restoringBlankFilters = true;


            try {

                Ext.Object.each(

                    blankFilterState,

                    function (
                        dataIndex,
                        enabled
                    ) {

                        if (!enabled) {
                            return;
                        }


                        var filterId =
                            getFilterId(
                                dataIndex
                            );


                        var existingFilter =
                            store.getFilters()
                                .get(
                                    filterId
                                );


                        if (existingFilter) {
                            return;
                        }


                        store.addFilter(
                            createBlankFilter(
                                dataIndex
                            )
                        );

                    }
                );

            }
            finally {

                restoringBlankFilters = false;

            }
        }


        // ========================================================
        // 清除所有“仅显示空白”
        //
        // 这是给 clearFilter() 使用的。
        // ========================================================

        function clearAllBlankFilters() {

            var store =
                grid.getStore();


            if (!store) {
                return;
            }


            clearingAllFilters = true;


            try {

                // -----------------------------------------------
                // 清除状态
                // -----------------------------------------------

                Ext.Object.each(

                    blankFilterState,

                    function (
                        dataIndex
                    ) {

                        setFilterHeaderColor(
                            dataIndex,
                            false
                        );

                    }
                );


                blankFilterState = {};


                // -----------------------------------------------
                // 删除所有我们自己的 Filter
                // -----------------------------------------------

                var filters =
                    store.getFilters();


                var removeList = [];


                filters.each(

                    function (filter) {

                        if (
                            filter &&
                            filter.id &&
                            String(
                                filter.id
                            ).indexOf(
                                '__blank_filter_'
                            ) === 0
                        ) {

                            removeList.push(
                                filter
                            );

                        }

                    }
                );


                Ext.Array.each(

                    removeList,

                    function (filter) {

                        filters.remove(
                            filter
                        );

                    }
                );

            }
            finally {

                clearingAllFilters = false;

            }

        }


        // ========================================================
        // ★ 包装 Ext.NET 的 clearFilter()
        //
        // 原来的:
        //
        //     grid.filterHeader.clearFilter()
        //
        // 现在变成:
        //
        //     先清除我们自己的“仅显示空白”
        //     再执行 Ext.NET 原来的 clearFilter()
        //
        // ========================================================

        if (
            grid.filterHeader &&
            grid.filterHeader.clearFilter &&
            !grid.filterHeader.__blankClearFilterWrapped
        ) {

            var originalClearFilter =
                grid.filterHeader.clearFilter;


            grid.filterHeader.clearFilter =
                function () {

                    // 清除“仅显示空白”
                    clearAllBlankFilters();


                    // 再执行 Ext.NET 原来的 clearFilter
                    return originalClearFilter.apply(
                        this,
                        arguments
                    );

                };


            grid.filterHeader.__blankClearFilterWrapped =
                true;
        }


        // ========================================================
        // 监听 Store Filter 改变
        //
        // 当用户:
        //
        // 1. 输入“店铺”
        // 2. 清空“店铺”
        // 3. 修改其它列筛选
        //
        // 都会经过这里。
        //
        // ========================================================

        var store =
            grid.getStore();


        if (store) {

            store.on(

                'filterchange',

                function () {

                    if (
                        restoringBlankFilters ||
                        clearingAllFilters
                    ) {
                        return;
                    }


                    Ext.defer(

                        function () {

                            restoreBlankFilters();

                        },

                        10
                    );

                }

            );

        }


        // ========================================================
        // 创建菜单分隔线
        // ========================================================

        var blankFilterSeparator =
            menu.add('-');


        // ========================================================
        // 创建“仅显示空白”
        // ========================================================

        var blankFilterItem =
            menu.add({

                itemId:
                    '__blank_filter_checkbox__',

                text:
                    '仅显示空白',

                xtype:
                    'menucheckitem',

                checked:
                    false,


                // ==================================================
                // Checkbox 点击
                // ==================================================

                handler:
                    function (item) {

                        var column =
                            currentColumn ||
                            menu.activeHeader;


                        if (
                            !column ||
                            !column.dataIndex
                        ) {
                            return;
                        }


                        var dataIndex =
                            column.dataIndex;


                        var store =
                            grid.getStore();


                        var filterId =
                            getFilterId(
                                dataIndex
                            );


                        // ==========================================
                        // 勾选
                        // ==========================================

                        if (item.checked) {


                            // 记录状态
                            blankFilterState[
                                dataIndex
                            ] = true;


                            // 删除旧 Filter
                            var oldFilter =
                                store.getFilters()
                                    .get(
                                        filterId
                                    );


                            if (oldFilter) {

                                store.getFilters()
                                    .remove(
                                        oldFilter
                                    );
                            }


                            // 添加 Filter
                            store.addFilter(
                                createBlankFilter(
                                    dataIndex
                                )
                            );


                            // 输入框变色
                            setFilterHeaderColor(
                                dataIndex,
                                true
                            );

                        }


                        // ==========================================
                        // 取消勾选
                        // ==========================================

                        else {


                            delete blankFilterState[
                                dataIndex
                            ];


                            var filter =
                                store.getFilters()
                                    .get(
                                        filterId
                                    );


                            if (filter) {

                                store.getFilters()
                                    .remove(
                                        filter
                                    );
                            }


                            // 恢复输入框
                            setFilterHeaderColor(
                                dataIndex,
                                false
                            );

                        }


                        menu.hide();

                    }

            });


        // ========================================================
        // 打开列菜单时同步状态
        // ========================================================

        menu.on(

            'beforeshow',

            function (menu) {

                currentColumn =
                    menu.activeHeader;


                if (
                    !currentColumn ||
                    !currentColumn.dataIndex
                ) {

                    blankFilterSeparator.hide();

                    blankFilterItem.hide();

                    return;
                }


                var dataIndex =
                    currentColumn.dataIndex;


                // Boolean 字段不显示
                if (
                    isBooleanField(
                        dataIndex
                    )
                ) {

                    blankFilterSeparator.hide();

                    blankFilterItem.hide();

                    return;
                }


                blankFilterSeparator.show();

                blankFilterItem.show();


                // 从独立状态读取
                var checked =
                    !!blankFilterState[
                        dataIndex
                    ];


                // 同步 Checkbox
                blankFilterItem.setChecked(
                    checked,
                    true
                );


                // 同步背景色
                setFilterHeaderColor(
                    dataIndex,
                    checked
                );

            }

        );


        // ========================================================
        // 初始化已有 Filter
        // ========================================================

        Ext.defer(

            function () {

                var store =
                    grid.getStore();


                if (!store) {
                    return;
                }


                var columns =
                    getColumns();


                Ext.Array.each(

                    columns,

                    function (column) {

                        if (
                            !column ||
                            !column.dataIndex
                        ) {
                            return;
                        }


                        var dataIndex =
                            column.dataIndex;


                        // Boolean 跳过
                        if (
                            isBooleanField(
                                dataIndex
                            )
                        ) {
                            return;
                        }


                        var filterId =
                            getFilterId(
                                dataIndex
                            );


                        var filter =
                            store.getFilters()
                                .get(
                                    filterId
                                );


                        if (filter) {

                            blankFilterState[
                                dataIndex
                            ] = true;


                            setFilterHeaderColor(
                                dataIndex,
                                true
                            );

                        }

                    }
                );


                restoreBlankFilters();

            },

            100
        );

    }


    // ============================================================
    // 对外暴露
    // ============================================================

    window.installBlankFilter =
        installBlankFilter;


    // ============================================================
    // 安装到指定 Grid
    // ============================================================

    installBlankFilter(
        Ext.getCmp('gcid')
    );

})();

 PS: 如果想要筛选显示某列 有值的数据行,则只需要在筛选处 输入:!=  即可

posted on 2026-09-15 13:48  wakaka_wka  阅读(5)  评论(0)    收藏  举报