javascript – 如何覆盖JQGrid中的默认搜索功能

我有一个JQGrid设置,搜索栏出现在顶部.对于文本字段,我希望搜索栏正常运行.在我使用一些完全匹配选项创建下拉列表的情况下也是如此.但是,对于日期字段或数字范围,我想创建一个允许用户按范围搜索的下拉列表.我假设在这些情况下我需要覆盖JQGrid的现有搜索功能并编写我自己的搜索功能.

我假设这是通过fn searchoption完成的.到目前为止,我已经达到了以下目标.这将完全按照我的意愿创建网格和搜索选项.但是,尝试进行任何搜索都会清除整个网格,大概是因为它不知道如何处理特殊日期和范围下拉列表.我很欣赏有关如何继续的见解.如果JQGrid中已存在此功能,请告诉我如何访问它?

顺便说一句,我想保持所有处理本地.像JQGrid这样的主要优点是消除了多个数据库请求的负载,并消除了这么多HTTP连接带来的延迟和开销.

<script>
    $("#grid1").jqGrid({
        datatype:       "local",
        height:         250,
        colNames:       ['CF Template', 'Error Date', 'Skey', 'Type', 'Summary'],
        colModel:       [

                                {   name: 'page_name',
                                    index: 'page_name',
                                    width: 400,
                                    sorttype: 'text',
                                    search:true,
                                    stype:'text'
                                }
                                , 
                                {   name: 'row_timestamp',
                                    index: 'row_timestamp',
                                    width: 100,
                                    sorttype: 'date',
                                    search:true,
                                    stype:'select',
                                    searchoptions: {
                                        value:{'0':'Any','2014-2-01_2014-2-28':'February','2014-3-01_2014-3-31':'March','2014-4-01_2014-4-30':'April'},
                                        dataEvents: [
                                            {
                                                type: 'change',
                                                fn: function(e) {
                                                    alert($('#gs_row_timestamp option:selected').val());
                                                    alert($('#gs_row_timestamp option:selected').text());
                                                    alert('4');
                                                }
                                            }
                                        ]
                                    }
                                }
                                , 
                                {   name: 'row_id',
                                    index: 'row_id',
                                    width: 100,
                                    sorttype: 'int',
                                    search:true,
                                    stype:'select',
                                    searchoptions: {
                                        value:{0:'Any',2:'0 - 12000000000',3:'12000000000 - 24000000000',4:'24000000000 - 36000000000',5:'36000000000 - 48000000000',6:'48000000000 - 60000000000'},
                                        dataEvents: [
                                            {
                                                type: 'change',
                                                fn: function(e) {
                                                    alert($('#gs_row_id option:selected').val());
                                                    alert($('#gs_row_id option:selected').text());
                                                    alert('2');
                                                }
                                            }
                                        ]
                                    }
                                }
                                , 
                                {   name: 'error_type',
                                    index: 'error_type',
                                    width: 100,
                                    sorttype: 'text',
                                    search:true,
                                    stype:'select',
                                    searchoptions: {
                                        value:{0:'Any',2:'Application',3:'Database',4:'Expression',5:'MissingInclude'},
                                        dataEvents: [
                                            {
                                                type: 'change',
                                                fn: function(e) {
                                                    alert($('#gs_error_type option:selected').val());
                                                    alert($('#gs_error_type option:selected').text());
                                                    alert('1');
                                                }
                                            }
                                        ]
                                    }
                                }
                                , 
                                {   name: 'error_summary',
                                    index: 'error_summary',
                                    width: 500,
                                    sorttype: 'text',
                                    search:true,
                                    stype:'text'
                                }

                        ],
        multiselect:    false,
        rowNum:         25,         // Number of rows shown per page; must also change down below
        pager:          '#pager1',  
        height:         250,        
        altRows:        true,                       // Allows for styling of alt rows
        altclass:       'altRowClass',              // Create striped rows
        viewrecords:    true,                       // Show recordcount in lower right corner
        ignoreCase:     true,                       // Case insensitive searches
        multiSort:      true,
    </script>

UPDATE

似乎使用e.stopImmediatePropagation()可以防止网格清除,但我不确定如何从那里控制搜索.我应该在定义搜索栏的行中查找设置一些特殊搜索功能而不是fn吗?

    $("#grid1").jqGrid('filterToolbar', {stringResult: true, searchOnEnter: false, defaultSearch : "cn"});

UPDATE

我想到一些样本数据可能会有所帮助.以下是在页面上定义的一些记录.它们在与JQGrid相同的页面上加载一次,然后所有搜索和过滤都应在本地进行.

        var mydata = [

                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\home.cfm"
                        , row_timestamp:    "2014-04-29 13:25:08.528"
                        , row_id:   "135200030"
                        , error_type:   "MissingInclude"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\home.cfm"
                        , row_timestamp:    "2014-04-29 13:24:48.575"
                        , row_id:   "135200040"
                        , error_type:   "MissingInclude"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Report\\repot_file_1.cfm"
                        , row_timestamp:    "2014-04-25 08:46:04.428"
                        , row_id:   "135200050"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Report\\repot_file_1.cfm"
                        , row_timestamp:    "2014-04-25 08:46:03.944"
                        , row_id:   "135200060"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Test\\jqtest.cfm"
                        , row_timestamp:    "2014-04-16 10:10:14.729"
                        , row_id:   "135200070"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\interface\\subFolder_1\\Activity\\loader_file_1.cfm"
                        , row_timestamp:    "2014-04-15 16:47:51.477"
                        , row_id:   "135200080"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\interface\\subFolder_1\\Blank\\loader_file_2.cfm"
                        , row_timestamp:    "2014-04-15 16:47:50.071"
                        , row_id:   "135200090"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\interface\\subFolder_1\\Activity\\loader_file_1.cfm"
                        , row_timestamp:    "2014-04-15 16:42:22.18"
                        , row_id:   "135300000"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\interface\\subFolder_1\\Blank\\loader_file_2.cfm"
                        , row_timestamp:    "2014-04-15 16:42:20.664"
                        , row_id:   "135300010"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\subFolder_12\\Activity\\action_page_1.cfm"
                        , row_timestamp:    "2014-04-08 11:53:38.01"
                        , row_id:   "135300020"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\subFolder_12\\Activity\\action_page_1.cfm"
                        , row_timestamp:    "2014-04-08 11:28:23.948"
                        , row_id:   "135300030"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\subFolder_12\\Activity\\action_page_1.cfm"
                        , row_timestamp:    "2014-04-08 11:07:24.76"
                        , row_id:   "135300040"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\subFolder_12\\Activity\\action_page_1.cfm"
                        , row_timestamp:    "2014-04-08 10:30:13.026"
                        , row_id:   "135300050"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\Common\\CustomTag\\stored_proc.cfm"
                        , row_timestamp:    "2014-04-08 09:03:21.588"
                        , row_id:   "135300060"
                        , error_type:   "Database"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\EdiErrorQueue\\INVN\\Frameset_1.cfm"
                        , row_timestamp:    "2014-02-19 09:52:43.078"
                        , row_id:   "135300070"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }
                , 
                {
                    page_name:  "C:\\inetpub\\wwwroot\\AppName\\AppFolder\\interface\\EdiErrorQueue\\INVN\\Frameset_1.cfm"
                        , row_timestamp:    "2014-02-19 09:46:10.906"
                        , row_id:   "135300080"
                        , error_type:   "Expression"
                        , error_summary:    "This is some sample text for example purposes.  Real data would be here."

                }

        ];
        for (var i = 0; i < mydata.length; i++)
            jQuery("#grid1").jqGrid('addRowData', i + 1, mydata[i]);
        jQuery("#grid1").setGridParam({ rowNum: 25 }).trigger("reloadGrid");

最佳答案 问题

实际上,jqGrid不允许您定义自己的过滤功能,以便在过滤本地数据时应用.您想要实现的目标是可能的,但远非直截了当.一个原因是jqGrid依赖于jLinq来执行搜索.但它并不是简单地调用jLinq进行搜索,将jLinq的代码复制粘贴到jqGrid代码中并在网格内部中间调用…这使得无法以干净的方式扩展搜索功能.

这就是为什么在尝试提供自己的更改事件处理程序时遇到困难的原因.处理程序的默认代码是:

function(){
    triggerToolbar();
    return false;
}

而triggerToolbar函数是一个“do everything”函数,它将重新加载数据,重新绘制完整的网格将所有库机器,以及中间的某个地方过滤数据而不用任何钩子来拦截搜索功能.

从这里,我可以看到三个解决方案:

>向jqGrid开发人员请求该功能
>修改jqGrid的代码.当我看到它时似乎很难这样做,同时确保你没有打破图书馆.
>黑客方式:让jqGrid相信数据来自服务器,并自行过滤

我将仅扩展第三个解决方案.我们的想法是使用jqGrid使用jQuery与服务器通信并在jQuery中注册ajax代理的事实.此代理将拦截所有ajax调用,并根据jqGrid发送的查询参数返回过滤的本地数据.这将在任何时候更改过滤器时执行所有jQuery机制,但它可以工作.

1.创建代理

第一步是将当前设置转换为jqGrid认为数据来自服务器的设置.您可以使用$.ajaxTransport(documentation)函数执行此操作,您可以在其中提供将在任何ajax调用之前调用的函数.根据选项,您可以决定是否要提供自己的对象来处理调用,或者让$.ajax()完成其通常的工作.我基于一个已知的url做出了这个决定,我们稍后会给jqGrid.这可以是任何东西,只要它不是跨域的(如果它可能包含查询参数,请不要使用像我这样的当前URL).这是代码:

var mydata = [ /* Your local data */ ];
var gridurl = window.location.href + "/mygrid";

$.ajaxTransport("json", function(options) {
  if(options.url.indexOf(gridurl) === 0) {
    return {
      send: function(headers, completeCallback) {
        setTimeout(function(){ //We still want the call to be asynchroneous
            completeCallback(200, "success", {json: mydata});
        }, 10);
      },
      abort: function() {
        //Do nothing
      }
    };
  }
});

并更新了jqGrid设置:

$("#grid1").jqGrid({
    url:       gridurl,
    datatype:  "json",
    height:    250,
    colNames:  ['CF Template', 'Error Date', 'Skey', 'Type', 'Summary'],
    /* ... */
});

//No call to addRowData

2.实施过滤器

完成步骤1后,您应该已经能够加载并显示网格.现在让我们修改代理,以便根据jqGrid在url中放置的搜索参数过滤数据.实际上,在处理远程数据时,jqGrid完全依赖服务器来过滤数据.它只是将查询参数附加到url,其中参数名称是列id,参数值是表单元素的值.例如:?page_name = home& row_timestamp = 2014-2-01_2014-2-28如果您在“错误日期”下拉列表中的“CF模板”和“二月”的文本字段中输入了“主页”.

所以我们首先需要的是一种解析URL查询参数的方法.您可以使用jQuery插件,编写自己的,或ask StackOverlfow 🙂

function getParameterByName(url, name) {
    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
        results = regex.exec(url);
    return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}

然后是一个过滤数据的函数.设计将主要取决于您和您的要求(您可以想象使用jLing使这更容易,就像jqGrid一样).我使用了一个基本示例,我们希望根据范围过滤row_id. row_id参数用_分割以解析范围的边界.请注意,在我的示例中,我只考虑row_id,但您必须为所有列编写过滤器,甚至是之前由jqGrid处理过的列(代理必须像服务器一样).

//Filtering split in two functions: 
// -one to parse the url and identify what filters to apply
// -one to do the actual filtering

function getFilterOptions(url) {
    var filterOptions = {};
    var row_id = getParameterByName(url, "row_id"); 
    if (row_id && row_id != "*") { //"*" == Any
        filterOptions.row_id = row_id.split("_");
    }
    return filterOptions;
}

//Uses Array.filter(), may require a polyfill on older browsers
function filterData(data, filterOptions) {
    return data.filter(function(row) { 
        if (filterOptions.row_id) {
            return filterOptions.row_id[0] <= row.row_id 
                && row.row_id <= filterOptions.row_id[1]
        }
        return true;
    });
}

然后更新代理以使用过滤器.

$.ajaxTransport("json", function(options) {
  //options.url is the query sent by jqGrid, including search parameters
  if(options.url.indexOf(gridurl) === 0) {
    var filterOptions = getFilterOptions(options.url); 
    return {
      send: function(headers, completeCallback) {
        setTimeout(function(){
            //this is what jqGrid will receive.
            var filteredData = filterData(mydata, filterOptions);
            completeCallback(200, "success", {json: filteredData});
        }, 10);
      },
      abort: function() {
        //Do nothing
      }
    };
  }
});

最后,在jqGrid设置中激活搜索.我已将joker值0替换为*,其他值的格式为< min> _< max>由getFilterOptions()解析:

$("#grid1").jqGrid({
    url:       gridurl,
    datatype:  "json",
    height:    250,
    colNames:  ['CF Template', 'Error Date', 'Skey', 'Type', 'Summary'],
    colModel:  [{/* template column */},
               {/* date column */},
               {   
                name: 'row_id',
                index: 'row_id',
                width: 100,
                sorttype: 'int',
                search:true,
                stype:'select',
                searchoptions: {
                    value: {
                        '*':'Any', //Notice: joker used in getFilterOptions
                        '0_12000000000':'0 - 12000000000', 
                        '12000000000_24000000000':'12000000000 - 24000000000',
                        /* ... */
                    }
                    //no event handler
                }
               },
               /* ... */
               ],
    /* ... */
});

3.完成过滤器实现,享受!

你还有一些工作要做,即设计和编写实际的过滤器,但是你有一个工作的解决方案,可以在jqGrid中进行自定义搜索.我在测试数据的本地设置上测试了它,没有遇到任何麻烦.如果我在将代码转换为此答案时忘记了某些内容,请告诉我.

点赞