views:

111

answers:

1

Hey Everybody!

So i've had JQGrid in my application for a while now and the speed of the grid hasnt really bothered me up until I started optimization.

If find that even if I have a small grid (20 items per page) the hover highlighting is slow and if the grid happens to need a scroll bar on the page, the scrolling of the page is really slow.

I've tried asynchronous posts and also loadonce:true and they both draw just as slow.

I'm using the jquery.ui.theme css.

I've removed paging all together so that the grid absolutely only contains 20 items on the screen and still the drawing of the hover is slow.

Just to be sure it wasnt anything else on my page I set the display of the grid to none, and the page ran fast as usual - just as i suspected.

Using IE8 debugger, I used the profiler to measure speeds of my javascript and html and these speeds were really fast - so it's definitely the drawing of the grid on screen.

I'd appreciated any and all help or suggestions for improved performance.

I'll attach my grid definition (it is quite big), in case you may think it could be something there:

$("#tblVariables").jqGrid({
        url: '/StudyAdmin/GetVariable.aspx?FilterType=' + Filter + '&SelectedFolder=' + SelectedFolder + '&SelectedGroup=' + SelectedGroup,
        datatype: "json",
        mtype: "POST",
        colNames: ['Variable Name', 'Hidden Original Text', 'Original Text', 'Label', 'Hidden', 'Groups', 'HiddenGroups'],
        colModel: [
            { name: 'VarName', index: 'VarName', editable: false },
            { name: 'VarOriginalText', index: 'VarOriginalText', hidden: true, editable: true, editrules: { edithidden: true} },
            { name: 'VarOriginalTextToShow', index: 'VarOriginalTextToShow', editable: false, sortable: false },
            { name: 'VarReportingText', index: 'VarReportingText', editable: true },
            { name: 'HiddenVar', index: 'HiddenVar', editable: true, edittype: "select", editoptions: { value: { "true": "True", "false": "False"}} },
            { name: 'Groups', index: 'Groups', editable: false },
            { name: 'HiddenGroups', index: 'HiddenGroups', hidden: true, editable: true, editrules: { edithidden: true} }
        ],
        editurl: "/StudyAdmin/Editvariable.aspx",
        height: "100%",
        gridComplete: function () {
            var grid = jQuery("#tblVariables");
            var ids = grid.jqGrid('getDataIDs');
            for (var i = 0; i < ids.length; i++) {
                var rowId = ids[i];
                var splitGroups = $('#tblVariables').getCell(rowId, 'HiddenGroups').split(",");
                if (splitGroups.length == 1 && splitGroups[0] == "") splitGroups = "";
                var GroupSelect = "<select id='Group_" + rowId + "' onchange='filterGroup(this)'>";
                if (splitGroups.length > 0) GroupSelect += "<option value='HasSelectGroup'>Select Group</option>";
                else GroupSelect += "<option value='NotHasSelectGroup'>No Groups</option>";
                for (var k = 0; k < splitGroups.length; k++) {
                    GroupSelect += "<option value='" + splitGroups[k] + "'>" + splitGroups[k] + "</option>";
                }
                //add all groups in here
                GroupSelect += "</select>";
                grid.jqGrid('setRowData', rowId, { Groups: GroupSelect });
            }
            setGridWidth($("#VariableGridContentConainer").width() - 19);
        },
        afterInsertRow: function (rowid, rowdata, rowelem) {
            $("#" + rowid).addClass('jstree-draggable');
        },
        ondblClickRow: function (id, ri, ci) {
            lastSelRow = id;
            $("#tblVariables").jqGrid('editRow', id, true);
        },
        onSelectRow: function (id) {
            if ($('#QuestionTree').find("#FQ" + id).attr("id") !== undefined) {
                $.jstree._focused().select_node("#FQ" + id);
            }
            if (id == null) {
                //$("#tblAnswers").setGridParam({ url: "/StudyAdmin/GetAnswers.aspx", page: 1 }).trigger('reloadGrid');
                $('#tblAnswers').GridUnload();
                loadAnswersGrid("-1");
            } else {
                //$("#tblAnswers").setGridParam({ url: "/StudyAdmin/GetAnswers.aspx?id=" + id, page: 1 }).trigger('reloadGrid');
                $('#tblAnswers').GridUnload();
                loadAnswersGrid(id);
                if (id && id !== lastSelRow) $("#tblVariables").jqGrid('saveRow', lastSelRow);
            }
        },
        viewrecords: true,
        rowNum: 20,
        loadonce: true,
        pager: jQuery('#pagernav'),
        sortname: 'VarName',
        sortorder: "asc",
        imgpath: '/Content/Images/',
        jsonReader: {
            root: "rows",
            page: "page",
            total: "total",
            records: "records",
            repeatitems: true,
            cell: "cell",
            id: "id"
        }
    });
+5  A: 

You don't post the full JavaScript code, so I write some remarks how you jqGrid can be optimized based on existing information.

  1. You should better avoid the usage of afterInsertRow and do the same work in gridComplete or loadComplete. Then you can add gridview: true parameter in the definition of jqGrid and the grid will be constructed quickly (read http://stackoverflow.com/questions/3025305/jqgrid-firefox-and-css-text-decoration-problem/3026421#3026421 for more details). Your current action in afterInsertRow can be easy replaced by jQuery('.jqgrow',jQuery('#tblVariables')).addClass('jstree-draggable'); in loadComplete or gridComplete.
  2. You construct the value of Groups column based on the contain of hidden HiddenGroups column. The data which you send from the server as the contain of Groups column seems be overwritten. You can construct the same contain of Groups column with respect of custom formatter of the Groups. Then probably you can remove unneeded HiddenGroups column at all. Look at http://stackoverflow.com/questions/2991267/jqgrid-editable-column-that-always-shows-a-select/2992064#2992064 for an example of custom formatter and at http://stackoverflow.com/questions/3054811/add-multiple-input-elements-in-a-custom-edit-type-field/3055626#3055626 as example of custom editing. Probably defining of custom unformater will be also interesting for you.
  3. It's a little the matter of taste, but the usage of formatter:'checkbox' for the column HiddenVar seems me appropriate. Moreover one can see that you send "True" or "False" strings from the server as the value for the column. Sending of 1 and 0 follows to the same results, but reduce the size of the data which are sent.
  4. You can reduce the size of your javascript if you remove some default values (like jsonReader) or deprecated values like imgpath (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:upgrade_from_3.4.x_to_3.5) and remove default values from colModel (like editable: false).

Description of some other general optimization ways for jqGrid you can find in http://stackoverflow.com/questions/2999955/what-is-the-best-way-to-optimize-my-json-on-an-asp-net-mvc-site/3001933#3001933.

UPDATED: Probably you don't really need to insert select elements in Groups. Instead of that you can do this only if the row is selected or is in editing mode. Removing of construction of the select elements from the whole Groups can improve performance of your grid and simplify the code. You can use editoptions with value as a function or use other possibilities of editoptions. Binding of onchange event to the select can be then replaced to dataEvents with type: 'change'.

Oleg
Hi there! I just had a look at my mail now. Thank you so much for your response! You really are very helpful ^_^I'll try some of the changes when I get back into the office and let you know my results.I really appreciate your well thought out and helpful reply.
Byron Cobb