0

I have a JQGrid and I've implemented a Collapse/Expand All button on the grid. it works but it's incredibly slow. Here's the code I've used, it takes 5-6 seconds for only 120 rows. is there any way to improve the performance of this? Thanks in advance!

        function CollapseAll() {
            $(".ui-icon-circlesmall-minus").trigger("click");
            $("#grid_toppager_left").find('.ui-icon-minus').removeClass('ui-icon-minus').addClass("ui-icon-plus");
        }

        function ExpandAll() {
            $(".ui-icon-circlesmall-plus").trigger("click");
            $("#grid_toppager_left").find('.ui-icon-plus').removeClass('ui-icon-plus').addClass("ui-icon-minus");
        }

        var groups = [];

        $("#grid").jqGrid({
                    url: '@Url.Action("GetLoanReport", "Report")',
                    datatype: "json",
                    emptyrecords: "0 records found",
                    height: "auto",
                    mtype: 'POST',
                    maxHeight: maxHeight,
                    postData: { startDate: $("#startDate").val(), endDate: $("#endDate").val(), selectedStatuses: selectedStatuses, selectedProductGroups: selectedProductGroups, assignedBranchList: assignedBranchList, assignedToList: assignedToList, createdByList: createdByList, approvedByList: approvedByList, uploadedByList: uploadedByList },
                    colNames: ['Branch', 'Status', 'Employee', 'Application ID', 'Customer Name', 'CustNo', 'Product Type', 'Description', 'Security Code', 'Final Rate', 'New Money', 'Total'],
                    colModel: [
                      { name: 'Branch', index: 'Branch', cellattr: function () { return ' title="my custom fixed tooltip for the column"'; } },
                      { name: 'Status', index: 'Status' },
                      { name: 'EmplName', index: 'EmplName' },
                      { name: 'ApplicationID', index: 'ApplicationID', sorttype: 'number', width: 125, sortable: true, formatter: createLink },
                      { name: 'CustName', index: 'CustName', formatter: custnameFormatter, width: 200, sortable: true },
                      { name: 'CustNo', index: 'CustNo', hidden: true, sortable: true },
                      { name: 'ProductType', index: 'ProductType', width: 100, sortable: true, sorttype: "text" },
                      { name: 'ProdDesc', index: 'ProdDesc', width: 250, sortable: true },
                      { name: 'SecurityCode', index: 'SecurityCode', width: 125, sortable: true },
                      { name: 'FinalRate', index: 'FinalRate', width: 75, align: "right", formatter: 'currency', formatoptions: { suffix: '%' }, sorttype: 'currency', sortable: true },
                      { name: 'NewMoney', index: 'NewMoney', formatter: 'currency', align: "right", sorttype: 'currency', formatoptions: { thousandsSeparator: ",", decimalPlaces: 0, prefix: "$" }, width: 125, sortable: true },
                      { name: 'TotalNewMoney', index: 'TotalNewMoney', formatter: 'currency', align: "right", sorttype: 'currency', formatoptions: { thousandsSeparator: ",", decimalPlaces: 0, prefix: "$" }, width: 125, sortable: true }
                    ],
                    jsonReader: {
                        repeatitems: false,
                        root: 'rowdata',
                        page: 'currpage',
                        total: 'totalpages',
                        records: 'totalrecords'
                    },
                    loadComplete: function () {
                        WaitIndicatorClose();

                        var reportSum = $("#grid").jqGrid('getCol', 'TotalNewMoney', false, 'sum');

                        $("#gridPager_right").html("<div id='sumTotal'>Number of Applications: " + $("#grid").getGridParam("records") + ",  Total: $" + formatMoney(reportSum, false, null, null, null, true, false) + '</div>');
                        $("#gridPager_right").show();

                        if (firstLoad == true) {
                            $(".ui-icon-circlesmall-plus, .ui-icon-circlesmall-minus").each(function () {
                                groups.push({ hid: $(this).closest("tr").attr("id"), collapsed: true });
                            });
                        } else {
                            $("#grid tr").each(function () {
                                for (var i = 0; i < groups.length; i++) {
                                    if ($(this).attr("id") === groups[i].hid) {
                                        if (groups[i].collapsed == false) {
                                            $("#grid").jqGrid('groupingToggle', groups[i].hid);
                                        }
                                    }
                                }
                            });
                        }

                        firstLoad = false;

                        $(".gridghead_0").attr("title", "Created by Branch");

                        $(".appLink").on("click", function (e) {
                            var appID = e.currentTarget.innerHTML;

                            ConfirmBox("This will redirect you to the Application page.  Are you sure?",
                                    function () {
                                        $.ajaxSetup({ cache: false });
                                        $.ajax({
                                            cache: false,
                                            type: "Get",
                                            url: "@Url.Action("VerifyAndSetApplicationID", "Application")",
                                            data: { "applicationID": appID },
                                            success: function (data) {
                                                if (data.Error) {
                                                    MessageBox(data.Error);
                                                } else {
                                                    if (data.Success) {
                                                        InitializeWriteAccess(appID);
                                                    } else {
                                                        MessageBox(data.NotFound);
                                                    }
                                                }
                                            },
                                            error: function (xhr, status, error) {
                                            },
                                            complete: function () {
                                            }
                                        });
                                    },
                                    function () {
                                    });

                        });
                    },
                    loadError: function () {
                        WaitIndicatorClose();
                    },
                    loadui: 'disable',
                    grouping: true,
                    onClickGroup: function (hid, collapsed) {
                        if ($(".ui-icon-circlesmall-plus").length == 0) {
                            $("#grid_toppager_left").find('.ui-icon-plus').removeClass('ui-icon-plus').addClass("ui-icon-minus");
                        } else {
                            $("#grid_toppager_left").find('.ui-icon-minus').removeClass('ui-icon-minus').addClass("ui-icon-plus");
                        }

                        for (var i = 0; i < groups.length; i++) {
                            if (groups[i].hid == hid) {
                                groups[i].collapsed = collapsed;
                            }
                        }

                        if (collapsed == true) {
                            $(".ui-icon-circlesmall-minus:hidden").each(function () {
                                for (var i = 0; i < groups.length; i++) {
                                    if (groups[i].hid == $(this).closest("tr").attr("id")) {
                                        groups[i].collapsed = true;
                                    }
                                }
                            });
                        }

                        $('#grid').trigger('reloadGrid');
                    },
                    groupingView: {
                        groupField: ['Branch', 'Status', 'EmplName'],
                        groupText: ['<b>{0}</b> Count: ({1})', '<b>{0}</b> Count: ({1})', '<b>Created by {0}</b> Count: ({1})'],
                        groupSummary: true,
                        groupColumnShow: false,
                        groupSummaryPos: "header",
                        groupCollapse: true
                    },
                    loadonce: true,
                    rowNum: 10000,
                    showrownumbers: true,
                    toppager: true,
                    shrinkToFit: true,
                    pgbuttons: false,
                    pginput: false,
                    pager: gridPager
                });
                $("#grid").jqGrid('navGrid', '#gridPager', { add: false, edit: false, del: false, find: false, search: false, refresh: false });
                $("#grid").jqGrid('navGrid', '#grid_toppager', { add: false, edit: false, del: false, find: false, search: false, refresh: false, width: 1093 });
                $("#grid").jqGrid('navButtonAdd', '#grid_toppager_left', {
                    caption: "Expand/Collapse All",
                    buttonicon: "ui-icon-plus",
                    onClickButton: function () {
                        if ($(".ui-icon-circlesmall-plus").length == 0) {
                            CollapseAll();
                        } else {
                            ExpandAll();
                        }

                        $('#grid').trigger('reloadGrid');
                    }
                });
                $("#grid").jqGrid('navButtonAdd', '#gridPager', {
                    caption: "Export to Excel",
                    onClickButton: function () {
                        fnExcelReport();
                    }
                });
            });
Mark Highfield
  • 443
  • 3
  • 9
  • 24
  • Which version of jqGrid you use (can use) and from which fork of jqGrid ([free jqGrid](https://github.com/free-jqgrid/jqGrid), commercial [Guiddo jqGrid JS](http://guriddo.net/?page_id=103334) or an old jqGrid in version <=4.7)? The code fragmants which you post gives too little information. Do you already loaded all the 120 rows in the grid? Where is the code which you use to create the grid? Do you have the demo online? In any way I'd recommend you to try to load free jqGrid 4.13.4. from CDN (see [here](https://github.com/free-jqgrid/jqGrid/wiki/Access-free-jqGrid-from-different-CDNs)). – Oleg Oct 24 '16 at 19:48
  • sorry, I'm using free jqGrid – Mark Highfield Oct 24 '16 at 19:51
  • Which version? Where is your JavaSctript code or the demo, which reproduces the problem? – Oleg Oct 24 '16 at 19:52
  • I believe it's version 4.13.3. I'm not sure if I can post a demo, it's for some banking software I write for work. This is all the code involved in the expanding/collapsing...I'm simply triggering a click() on each icon depending on whether it's plus or minus. the .trigger() call takes the time – Mark Highfield Oct 24 '16 at 19:55

1 Answers1

0

I suppose that you have the problem in the code which you don't posted.

I created the demo with 120 rows of dummy data and "Expand/Collapse All" button in the pager. It uses the current (4.13.4) version of free jqGrid. The performance of the same demo with the previous (4.13.3) version of free jqGrid is the same in my tests. You can try it and see that the performance is good.

I used a little modified code of "Expand/Collapse All" button, but it should have no difference for the performance of expanding/collapsing.

.jqGrid("navButtonAdd", {
    caption: "Expand/Collapse All",
    id: "expand_collapse_all",
    buttonicon: "ui-icon-plus",
    onClickButton: function () {
        var gridId = this.id, icons = this.p.treeIcons,
            $expandCollapseAll = $("#expand_collapse_all");
        if ($expandCollapseAll.find('.ui-icon-minus').length > 0) {
            $expandCollapseAll.find('.ui-icon-minus')
                .removeClass('ui-icon-minus')
                .addClass("ui-icon-plus");
            $(".tree-minus").trigger("click");
        } else {
            $expandCollapseAll.find('.ui-icon-plus')
                .removeClass('ui-icon-plus')
                .addClass("ui-icon-minus");
            $(".tree-plus").trigger("click");
        }
    }
});

UPDATED: I find that the code of onClickGroup and loadComplete, which you last posted, is the origin of your performance problem. Try the demo, which has 1000 rows instead of 120 rows in your case. The expanding of 1000 rows is slow, but it's about 0,5 sec on my computer on IE11 and about 190 ms in Chrome. It's far from 5-6 seconds, which you reported.

The next demo hide the grid temporary before expanding/collapsing of all rows and then show it back. It improves the performance additionally. The last demo expand all on my computer in 160 ms in Chrome and in 350 ms in IE11.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • ok, I've added the entirety of the grid. I'm doing a lot of work with the groups array. What I've done with that is trying to save the collapse/expanded state of each group so that when I sort and the grid reloads, it doesn't collapse all the groups by default. Maybe you know a better way of doing that as well. Thanks! – Mark Highfield Oct 25 '16 at 12:32
  • @MarkHighfield: The questions from your last comment seems to me absolute independent from your original question - the performance of expanding/collapsing the TreeGrid in free jqGrid. Look at [the old answer](http://stackoverflow.com/a/9202378/315935), where I describe the way of saving the TreeGrid state. I see that you modified the code of your question once more. Now one can see that you use data grouping instead of TreeGrid. Sorry, but you should formulate the question clear enough at the beginning. I can't create a lot of different demos for you guessing what you really need. – Oleg Oct 25 '16 at 12:52
  • I apologize if my wording wasn't clear. I'm simply trying to improve the performance of my expand/collapse all button for my groupings – Mark Highfield Oct 25 '16 at 12:57
  • Any idea why the expand/collapse all performance is so slow based on the code posted? – Mark Highfield Oct 25 '16 at 14:29
  • @MarkHighfield: I find that the code of `onClickGroup` and `loadComplete`, which you use, is the origin of your performance problem. Try [**the demo**](http://www.ok-soft-gmbh.com/jqGrid/OK/performane-1000-free-grid-groupingAll.htm), which has 1000 rows instead of 120 rows in your case. The expanding of 1000 rows is slow, but it's about 0,5 sec on my computer on IE11 and about 190 ms in Chrome. It's far from 5-6 seconds, which you reported. – Oleg Oct 25 '16 at 20:43
  • @MarkHighfield: Do you have any progress in creating the demo, which demonstrates any performance problem in collapsing/expanding of data groups? I repeat, that I have good performance in my tests. – Oleg Oct 29 '16 at 20:56
  • @MarkHighfield: Independent from your current question you try to *save* in some way which groups are collapsed and then to create the grid with some *collapsed* groups. I implemented some new features in free jqGrid, which could simplify such work. Look at [the demo](http://www.ok-soft-gmbh.com/jqGrid/OK/grouping2-groupCollapseAsFunction.htm), which hold some groups collapsed. [Another demo](http://www.ok-soft-gmbh.com/jqGrid/OK/grouping2-groupCollapseAsFunction1.htm) demonstrates how to get information about the collapsing/expanding group header inside of `onClickGroup`. – Oleg Oct 29 '16 at 21:01