jqGrid FilterToolbar 与主要工作的日期范围选择器

jqGrid FilterToolbar with mostly working daterange picker

我正在使用免费的 jqGrid v4.12.1。 (无法 post 链接到 fiddle,因此代码遵循 post)

主要问题是我们正在尝试使用 filterToolbar 完成所有 searching/filtering。几周前 Oleg 曾帮助将日期推送到搜索模式,但要求已更改为在 filterToolbar 中使用日期 运行ge 选择器。我们大多在那里。使用 Dan Grossman 的 bootstrap date运行ge picker 并调用自定义函数,它就像一个魅力。 Entering DateRangeFirst

当您 select 另一个值(如发票金额)时,问题最初出现了。然后它将覆盖日期 运行ge 并将所有值 "ge" 赋予开始日期。所以它看到的是字符串的开始日期。为了避免这种情况,我在 beforeSearch 中再次调用了 invoiceDateSearch 函数。这样它 运行 函数再次识别开始日期和结束日期以及我们要求的新值。

现在发生的事情是,如果我先输入任何其他值,然后 select 日期 运行ge,日期 运行ge 将不会触发,直到我键入一些其他搜索条件并将其退出。 AnyOther value first 它甚至无法识别输入 运行ge 的日期,尽管它显然存在。 triggerToolbar,在发票日期搜索函数中调用重新加载网格。

使用 beforeSearch 时,将日期 运行ge 保留为日期 运行ge 而不是字符串...无论工具栏被触发的频率如何以及值从任何其他工具栏中退出的频率如何字段,这很棒。它的缺点是,如果用户首先输入日期 运行ge 以外的值,则日期 运行ge 不起作用...除非输入后续字段。不使用它,在第一次使用后将日期 运行ge 转换为字符串,输入或过滤的任何其他值都需要重新 运行 日期参数,因为它给出的每个日期都大于开始日期。

我在进行故障排除时在网格上放置了高级搜索。我想将其取下(或至少是按钮),因为用户只想使用 toolbarFilter。

我的问题是,如何让日期 运行ge 选择器与其他列值协同工作?一次 运行 两个日期选择器是否存在问题?单一日期日期选择器在使用时根本没有响应。它会将日期放在那里,一旦触发另一个字段,它就会响应,但不会自己响应。

对不起,如果我 "info dumped" 我是新手。我已经为此搜索了很多帮助,但找不到任何东西。如果我继续破解这个,我会撕掉我的工作! :O

在此先感谢您的帮助或指导! $(函数(){ "use strict";

var $grid = $("#vGrid2"),
lastSel;
function modifySearchingFilter(separator) {
    var i,
        l,
        rules,
        rule,
        parts,
        j,
        group,
        str,
        filters = $.parseJSON(this.p.postData.filters);
    if (filters && typeof filters.rules !== 'undefined' && filters.rules.length > 0) {
        rules = filters.rules;
        for (i = 0; i < rules.length; i++) {
            rule = rules[i];
            if (rule.op === 'cn') {
                // make modifications only for the 'contains' operation
                parts = rule.data.split(separator);
                if (parts.length > 1) {
                    if (typeof filters.groups === 'undefined') {
                        filters.groups = [];
                    }
                    group = {
                        groupOp: 'AND',
                        groups: [],
                        rules: []
                    };
                    filters.groups.push(group);
                    for (j = 0, l = parts.length; j < l; j++) {
                        str = parts[j];
                        if (str) {
                            // skip empty '', which exist in case of two separators of once
                            group.rules.push({
                                data: parts[j],
                                op: rule.op,
                                field: rule.field
                            });
                        }
                    }
                    rules.splice(i, 1);
                    i--; // to skip i++
                }
            }
        }
        this.p.postData.filters = JSON.stringify(filters);
    }
};
//TODO: search is filtering in the grid but only from start date and either ge or le start date based on which is first in the column
//TODO: (cont)model.  Need to see why end date is not picking up from function.

function invoiceDateSearch($subGrid) {
    var postData = $subGrid.getGridParam("postData");
    // If there is no post data for some reason, get outta here
    if (!postData) {
        return;
    }
    // Make sure the filters object is constructed
    var field = "InvoiceDate";
    if (!postData.filters) {
        postData.filters = {
            groupOp: "AND",
            rules: []
        }
    } else {
        postData.filters = jQuery.jgrid.parse(postData.filters);
        // Need to clear out existing invoice date rules
        for (var i = postData.filters.rules.length - 1; i >= 0; i--) {
            if (postData.filters.rules[i].field === field) {
                postData.filters.rules.splice(i, 1);
            }
        }
    }

    var dateRangeString = $("#gs_InvoiceDate").val();
    if (dateRangeString.length > 0) {
        var dateRange = dateRangeString.split("-");
        var startDate = dateRange[0];
        var endDate;
        if (dateRange.length == 1) {
            endDate = dateRange[0];
        } else {
            endDate = dateRange[1];
        }
        postData.filters.rules.push({ "field": field, "op": "ge", "data": startDate.trim() });
        postData.filters.rules.push({ "field": field, "op": "le", "data": endDate.trim() });
        postData.filters = JSON.stringify(postData.filters);
        // Need to set the grid's search to true, not the postData's

        $subGrid.setGridParam({ search: true });
        $subGrid.trigger("reloadGrid", [{ current: true, page: 1 }]);
    }
}
function paymentDateSearch($subGrid) {
    var postData = $subGrid.getGridParam("postData");
    // If there is no post data for some reason, get outta here
    if (!postData) {
        return;
    }
    // Make sure the filters object is constructed
    var field = "PaymentDate";
    if (!postData.filters) {
        postData.filters = {
            rules: []
        }
    } else {
        postData.filters = jQuery.jgrid.parse(postData.filters);
        // Need to clear out existing invoice date rules
        for (var i = postData.filters.rules.length - 1; i >= 0; i--) {
            if (postData.filters.rules[i].field === field) {
                postData.filters.rules.splice(i, 1);
            }
        }
    }

    var dateString = $("#gs_PaymentDate").val();
    if (dateString.length > 0) {
        var startDate = dateRange[0];

        postData.filters.rules.push({ "field": field, "op": "eq", "data": startDate.trim() });
        postData.filters = JSON.stringify(postData.filters);
        // Need to set the grid's search to true, not the postData's

        $subGrid.setGridParam({ search: true });
        $subGrid.trigger("reloadGrid", [{ current: true, page: 1 }]);
    }
}
//**TO overwrite jquery.ui icons and use fontAwesome.  extending allows for customization of fA icons set as default in grid**//
$.extend(true, $.jgrid.icons.fontAwesome, {
    common: "fa",
    sort: {
        common: "fa-sort fa-lg"
        //asc: "fa-sort",
        //desc: "fa-sort"
    },
    nav: {
        common: "fa",
        refresh: "fa-recycle fa-lg"
    }

});
//**TOOLTIP ADD ON**//
$("[title]").qtip({
    position: {

        my: "bottom center",
        at: "top center",
        viewport: $(window)
    }
});



//**PRIMARY GRID**//  
$grid.jqGrid({
    url: "VendInvoice/Vendor",
    datatype: "local",
    data: gridData,
    colNames: ["ID", "Vendor Number", "Vendor Name", "dba", "VendorDbaCombo"],
    colModel: [
        { key: true, name: "ID", width: 0, hidden: true, sortable: false, search: false },
        {
            key: false,
            title: false,
            name: "VendorNo",
            index: "VendorNo",
            width: 100,
            sortable: true,
            search: true,
            stype: "text",
            searchoptions: {
                sopt: ["cn"],
                attr: { title: "Enter all or part of a Vendor Number." },
                clearSearch: false
            }
        },
        {
            key: false,
            title: false,
            name: "VendorName",
            //index: "VendorName",
            width: 500,
            sortable: true,
            search: true,
            clearSearch: false,
            stype: "text",
            searchoptions: {
                sopt: ["cn"],
                clearSearch: false, //removes X in column filters
                attr: {
                    title: "Enter a Vendor Name. SEARCHTIP: Once you start typing, you will begin returning filtered data. To broaden results returned provide less information, to narrow results provide more.",
                    maxlength: 9080,
                    dataInit: function (elem) {
                        $(elem).width(600);
                    }
                }
            }
        },
        {
            key: false,
            title: false,
            name: "Dba",
            index: "Dba",
            width: 500,
            sortable: true,
            search: true,
            stype: "text",
            searchoptions: {
                sopt: ["cn"],
                attr: { title: "Enter all or part of a dba." },
                clearSearch: false
            }
        },
        { key: false, name: "VendorDbaCombo", index: "VendorDbaCombo", width: 1, hidden: true }
    ],

    //**PRIMARY GRID PROPERTIES**//
    cmTemplate: { autoResizable: true, editable: true },
    iconSet: "fontAwesome",
    hidegrid: false,
    forceFit: true,
    caption: "Vendor Results",
    ignoreCase: true,
    gridview: true,
    autoencode: true,
    pager: "#Pager",
    toppager: true,
    rowNum: 25,
    rowList: [5, 10, 25],
    autowidth: true,
    height: "auto",
    viewrecords: true,
    loadonce: true,
    sortName: "VendorName",
    sortOrder: "ASC",
    viewsortcols: [true, "vertical", true],
    forceClientSorting: true,
    multiselect: true,
    setGridWidth: 980,
    loadtext: "Fetching your data, back in a jiff!",
    emptyrecords: "There were no records, try narrowing your search criteria",
    loadComplete: function () {
        $(this).find(">tbody>tr.jqgrow:visible:odd").addClass("myAltRowClass");
    },
    onSelectRow: function (row_id) {
        $grid.jqGrid("toggleSubGridRow", row_id);
        if (row_id !== lastSel && typeof lastSel !== "undefined") {
            $grid.jqGrid("setRowData", row_id, false, "myNormal");
        }
        $grid.jqGrid("setRowData", row_id, false, "myBold");
        lastSel = row_id;



    },

    //**SET SUBGRID**//
    subGrid: true,
    subGridOptions: {
        plusicon: "fa fa-plus-square-o",
        minusicon: "fa fa-minus-square-o",
        reloadOnExpand: false,
        expandOnLoad: false,
        delayOnLoad: 50

    },
    jsonReader: {
        id: "id",
        root: "rows",
        total: "total",
        records: "records",
        subgrid: {
            root: "rows",
            repeatitems: true, //must be true in subgrid and false in main grid
            cell: ""
        }

    },
    subGridRowExpanded: function (subgrid_id, row_id) {
        var subgrid_table_id, pager_id;
        subgrid_table_id = subgrid_id + "_t";

        var selectedrow = $(this).jqGrid('getRowData', row_id);
        pager_id = "p_" + subgrid_table_id;

        var stat = function (subgrid_id, row_id) {
            $("#vGrid2").jqGrid("setSelection", "row_id"); //Test to set selection for toggle
        }


        //**SUBGRID**//
        $("#" + subgrid_id).html("<table id='" + subgrid_table_id + "'class='scroll'></table><div id='" + pager_id + "'class='scroll'></div>");
        $("#" + subgrid_table_id).jqGrid({
            url: "VendInvoice/VendInvoiceSubGridData?vendorID=" + row_id,
    datatype: "local",
            data: subgridData[rowId],
            postData: {
                vendorID: row_id,

            },
            colNames: ["vendorID", "Invoice Status", "Invoice No", "Invoice Date", "Invoice Amount($)", "Payment Date", "Check or ACH Number", "Check or ACH Amount($)", "Encashment Date"],
            colModel: [
                { name: "vendorID", key: true, index: "vendorID", hidden: true, width: 0 },
                {
                    name: "InvoiceStatus",
                    title: false,
                    index: "InvoiceStatus",
                    width: 140,
                    sortable: true,
                    search: true,
                    formatter: "select",
                    stype: "select",
                    searchoptions: {
                        sopt: ["cn"],
                        attr: { title: "If part of your search criteria, select an invoice status from the drop-down menu." },
                        value: ":Select (All);Paid:Paid;Processing for Payment:Processing for Payment;Reviewing:Reviewing"
                    }

                },
                {
                    name: "InvoiceNo",
                    title: false,
                    index: "InvoiceNo",
                    width: 125,
                    sortable: true,
                    search: true,
                    stype: "text",
                    searchoptions: {
                        sopt: ["cn", "eq"],
                        attr: { title: "Enter all or part of an invoice number." },
                        clearSearch: false

                    }

                },
                {
                    name: "InvoiceDate",
                    title: false,
                    index: "InvoiceDate",
                    width: 135,
                    formatter: "date",
                    formatoptions: { srcformat: "m/d/Y", newformat: "m/d/Y" },
                    jsonmap: function (obj) {
                        var d = new Date(parseInt(obj.matchstartDate, 10));


                        return d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate()
                    },
                    sortable: true,
                    sorttype: "date",
                    editable: true,
                    search: true,
                    stype: "text",
                    searchoptions: {
                        sopt: ["ge", "le"],
                        clearSearch: false,
                        attr: { title: "Click in the box to open the date range picker." },
                        dataInit: function (elem) {
                            $(elem).daterangepicker({
                                dateFormat: 'mm/dd/yy',
                                changeYear: true,
                                changeMonth: true,
                                todayHighlight: true,
                            });
                            //ranges: {
                            //  "Yesterday": [moment(), subtract(1, 'days'), moment().subtract(1, 'days')],
                            //  "Last 7 days": [moment().subtract(6, 'days'), moment()],
                            //  "Last Month": [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')],
                            //  "This YTD": [moment().startOf('year'), moment().endOf('year')],
                            //  "LastYear": [moment().subtract(1,'year').startOf('year'), moment.subtract(1,'year').endOf('year')]
                            //    }

                            $(document).on('apply.daterangepicker', function () {
                                var $subGrid = $("#" + subgrid_table_id);
                                invoiceDateSearch($subGrid);

                            });
                        }
                    }

                },
                {
                    name: "InvoiceAmount",
                    title: false,
                    index: "InvoiceAmount",
                    width: 95,
                    sortable: true,
                    sorttype: "float",
                    formatter: "currency",
                    formatoptions: {
                        //prefix: "$",
                        suffix: "", thousandsSeparator: ",", decimalPlaces: 2
                    },
                    search: true,
                    stype: "text",
                    searchoptions: {
                        sopt: ["eq"],
                        attr: { title: "Enter an invoice amount." },
                        clearSearch: false
                    }
                },
                {
                    name: "PaymentDate",
                    title: false,
                    index: "PaymentDate",
                    width: 135,
                    formatter: "date",
                    formatoptions: { srcformat: "m/d/Y", newformat: "m/d/Y" },
                    jsonmap: function (obj) {
                        var d = new Date(parseInt(obj.matchstartDate, 10));


                        return d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate()
                    },
                    sortable: true,
                    sorttype: "date",
                    editable: true,
                    search: true,
                    stype: "text",
                    searchoptions: {
                        sopt: ["eq"],
                        clearSearch: false,
                        attr: { title: "Click in the box to open the date range picker." },
                        dataInit:

                            function (el) {
                                $(el).datepicker({
                                    dateFormat: 'mm/dd/yy',
                                    changeYear: true,
                                    changeMonth: true,
                                    todayHighlight: true,
                                    orientation: "bottom",
                                    immediateUpdates: true,
                                    autoclose: true
                                }).on('changeDate', function () {
                                    var $subGrid = $("#" + subgrid_table_id);
                                    paymentDateSearch($subGrid);
                                    $subGrid.setGridParam({ search: true });
                                    $subGrid.trigger("reloadGrid", [{ current: true, page: 1 }]);

                                });

                        }
                    }


                },
                {
                    name: "PaymentNo",
                    title: false,
                    index: "PaymentNo",
                    width: 115,
                    sortable: true,
                    search: true,
                    stype: "text",
                    searchoptions: {
                        sopt: ["cn", "eq"],
                        attr: { title: "Enter all or part of a Check or ACH Number." },
                        clearSearch: false
                    }
                },
                {
                    name: "CheckAmount",
                    title: false,
                    index: "CheckAmount",
                    width: 95,
                    sortable: true,
                    sorttype: "float",
                    formatter: "currency",
                    formatoptions: { suffix: "", thousandsSeparator: ",", decimalPlaces: 2 },
                    search: true,
                    stype: "text",
                    searchoptions: {
                        sopt: ["eq"],
                        attr: { title: "Enter a payment amount." },
                        clearSearch: false
                    }
                },
                {
                    name: "EncashmentDate",
                    title: false,
                    index: "EncashmentDate",
                    width: 100,
                    sortable: true,
                    sorttype: "date",
                    formatter: "date",
                    formatoptions: { srcformat: "m/d/Y", newformat: "m/d/Y" },
                    search: false
                }
            ],

            //**SUBGRID PROPERTIES**//

            cmTemplate: {
                align: "center",
                autoResizeable: true
            },
            idPrefix: "_s",
            iconSet: "fontAwesome",
            loadonce: true,
            loadtext: "Grabbing those invoice, this may take a second!",
            autoencode: true,
            toppager: true,
            autowidth: true,
            sortable: true,
            showOneSortIcon: true,
            autoResizing: { widthOfVisiblePartOfSortIcon: 13 },
            viewsortcols: [true, "vertical", true],
            multiselect: true,
            height: "auto",
            rowNum: 500,
            rowList: [25, 50, 100, 250, 500],
            gridview: true,
            viewrecords: true,
            emptyrecords: "There were no records, try narrowing your search criteria",
            prmNames: {
                id: "vendorID"
            },
            pager: "#" + pager_id,
            loadComplete: function () {
                $(this).find(">tbody>tr.jqgrow:visible:odd").addClass("myAltRowClass2");
            },
            beforeSelectRow: function () {
                return false;
            }

        });
        jQuery("#" + subgrid_table_id).jqGrid("navGrid", "#" + pager_id, {
            edit: false,
            add: false,
            del: false,
            search: true,
            refresh: true,
            refreshtext: "Refresh Invoice Results",
            cloneToTop: true
        },
            {},
            {},
            {},
            {
            multipleSearch: true,
        });
        jQuery("#" + subgrid_table_id).jqGrid("navButtonAdd", "#" + pager_id, {
            caption: "Export to Excel",
            buttonicon: "fa-file-excel-o",
            onClickButton: function (e) {
                exportData(e, "#" + subgrid_table_id);
            },
            position: "last"
        });
        jQuery("#" + subgrid_table_id).jqGrid("filterToolbar", {
            stringResult: true,
            searchOnEnter: false,
            ignoreCase: true,
            autoSearch: true,
            autosearchDelay: 1000,
            attr: {
                style: "width: auto;padding:0;max-width:100%"
            },
            defaultSearch: "cn",
            //beforeSearch: function () {
            //  var $subGrid = $("#" + subgrid_table_id);
            //  invoiceDateSearch($subGrid);
            //  $subGrid.trigger("reloadGrid", [{ current: true, page: 1 }]);
            //}
        });
        $("[title]").qtip({
            position: {
                my: "bottom center",
                at: "top center",
                viewport: $(window)

            }
        });
        var names = [
            "Invoice Status", "Invoice No", "Invoice Date", "Invoice Amount", "Payment Date",
            "Check or ACH No", "Check or ACH Amount", "Encashment Date"
        ];
        var mydata = [];
        var i, j;
        if (mydata != null) {
            for (i = 0; i < mydata.length; i++) {
                mydata[i] = {};
                for (j = 0; j < mydata[i].length; j++) {
                    mydata[i][names[j]] = mydata[i][j];
                }
            }
        }
        for (var i = 0; i <= mydata.length; i++);
        $("#" + subgrid_table_id).jqGrid('addRowData', i + 1, mydata[i]);

    }
}).jqGrid("navGrid", "#Pager", {
    edit: false,
    add: false,
    del: false,
    search: false,
    refresh: true,
    refreshtext: "Refresh Results",
    cloneToTop: true
}).jqGrid("filterToolbar", {
    stringResult: true,
    searchOnEnter: false,
    ignoreCase: true,
    autoSearch: true,
    autosearchDelay: 1000,
    attr: {
        style: "width: auto;padding:0;max-width:100%"
    },
    defaultSearch: "cn",
    beforeSearch: function () {
        modifySearchingFilter.call(this, " ");
    }
}).jqGrid("gridResize");

//**TOOLTIP ADD ON**//
$("[title]").qtip({
    position: {

        my: "bottom center",
        at: "top center",
        viewport: $(window)
    }
});

//**HIDE 'SELECT ALL' CHECKBOX**  call after grid is loaded//
$("#cb_" + $grid[0].id).hide();
$("#vGrid2").jqGrid("hideCol", "subgrid");


//**CUSTOM TOOLTIP TEXT FOR COLUMN HEADERS IN PRIMARY GRID**//   
var setTooltipsGrid = function (grid, iColumn, text) {
    var thd = jQuery("thead:first", grid[0].grid.hDiv)[0];
    jQuery("tr.ui-jqgrid-labels th:eq(" + iColumn + ")", thd).attr("title", text);

};
$(".hasTooltip").each(function () {
    $(this).qtip({
        content: {
            text: $(this).next("div")
        }
    });

});

//setTooltipsGrid($("#vGrid2"), 0, "If exporting, ensure ONLY the row you wish to export is selected. Remove any unnecessary checks in this column.");

//**EXPORT TO EXCEL-CSV**//

function exportData(e, row_id) {

    var subGrid = jQuery(row_id).getDataIDs(); // Get all the ids in array
    var label = jQuery(row_id).getRowData(subGrid[0]); // Get First row to get the labels

    var selRowIds = jQuery(row_id).jqGrid('getGridParam', 'selarrrow');

    var obj = new Object();
    obj.count = selRowIds.length;

    if (obj.count) {

        obj.items = new Array();

        var elem;

        for (elem in selRowIds) {
            if (selRowIds.hasOwnProperty(elem)) {
                obj.items.push(jQuery(row_id).getRowData(selRowIds[elem]));
            }
        }

        var json = JSON.stringify(obj);

        JSONToCSVConvertor(json, "csv", 1);
    }
}


function JSONToCSVConvertor(JSONData, ReportTitle, ShowLabel) {

    //If JSONData is not an object then JSON.parse will parse the JSON string in an Object
    var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
    var CSV = '';
    //This condition will generate the Label/Header
    if (ShowLabel) {
        var row = "";

        //This loop will extract the label from 1st index of on array
        for (var index in arrData.items[0]) {
            //Now convert each value to string and comma-seprated
            row += index + ',';
        }
        row = row.slice(0, -1);
        //append Label row with line break
        CSV += row + '\r\n';
    }

    //1st loop is to extract each row
    for (var i = 0; i < arrData.items.length; i++) {
        var row = "";
        //2nd loop will extract each column and convert it in string comma-seprated
        for (var index in arrData.items[i]) {
            row += '"' + arrData.items[i][index].replace(/(<([^>]+)>)/ig, '') + '",';
        }
        row.slice(0, row.length - 1);
        //add a line break after each row
        CSV += row + '\r\n';
    }

    if (CSV == '') {
        alert("Invalid data");
        return;
    }

    //*** FORCE DOWNLOAD ***//
    //will generate a temp "a" tag
    var link = document.createElement("a");
    link.id = "lnkDwnldLnk";

    //this part will append the anchor tag and remove it after automatic click
    document.body.appendChild(link);

    var csv = CSV;
    var blob = new Blob([csv], { type: 'text/csv' });

    var myURL = window.URL || window.webkitURL;

    var csvUrl = myURL.createObjectURL(blob);
    var filename = 'UserExport.csv';
    jQuery("#lnkDwnldLnk")
    .attr({
        'download': filename,
        'href': csvUrl
    });

    jQuery('#lnkDwnldLnk')[0].click();
    document.body.removeChild(link);

}

});

在我看来,使用 自定义操作 是解决您问题的最佳方法。当然可以使用 filterToolbarbeforeSearch 回调来修改过滤器,但它的操作级别太低,在搜索对话框中不起作用。

我建议您阅读描述此功能的 the wiki article。它提供了一个带有 "numeric IN" 操作的示例,您可以根据需要轻松修改它。 filter 回调获取 options 您需要的所有信息,回调应该只验证测试项 (options.item) 的数据是否在日期范围选择器 (options.searchValue)。我想你会得到小代码,顺便解决你的问题。

最后的评论:我建议您升级到最新的 4.13.0 版本,它修复了一些错误,在某些情况下提高了性能并提供了 the readme 中描述的新功能。