Your question is not new. Many times, the corresponding function request was requested in the trirand forum or in stackoverflow. I give another answer on a closed question some time ago.
Now, after reading your question, I decided not to make the perfect solution that supports all the jqGrid functions (which is too complicated right away). Instead, I decide to create a solution that can be used in many cases, but which has some limitations.
The demo shows my first results:

Limitations:
- grid columns cannot be changed. I use the
cmTemplate: {resizable: false} parameter in the demo to set resizable: false in all grid columns. sortable: true not supportedshowCol , hideCol or columnChooser is not currently supported, but I am sure you can fix the problems quickly. Column- on which the additional column of the column will be placed, must have the same width . If the columns have different widths, the total column width will be automatically divided into columns.
On the other hand, everything works without any problems in all my tests with other popular options such as shrinkToFit: false , autowidth: true or by changing the grid width using the setGridWidth method (with or without compression).
Now first about using the function. I wrote the insertColumnGroupHeader function, which I use in the above example as
insertColumnGroupHeader(grid, 'amount', 3, '<em>Information about the Price</em>');
Inserts an additional column header with the HTML fragment "Price Information" into 3 columns, starting with the sum of the column. So using is pretty simple. Of course, you can use only any text, for example, "Price Information" as an additional column heading.
The insertColumnGroupHeader function has the following code:
var denySelectionOnDoubleClick = function ($el) { // see https://stackoverflow.com/questions/2132172/disable-text-highlighting-on-double-click-in-jquery/2132230#2132230 if ($.browser.mozilla) {//Firefox $el.css('MozUserSelect', 'none'); } else if ($.browser.msie) {//IE $el.bind('selectstart', function () { return false; }); } else {//Opera, etc. $el.mousedown(function () { return false; }); } }, insertColumnGroupHeader = function (mygrid, startColumnName, numberOfColumns, titleText) { var i, cmi, skip = 0, $tr, colHeader, iCol, $th, colModel = mygrid[0].p.colModel, ths = mygrid[0].grid.headers, gview = mygrid.closest("div.ui-jqgrid-view"), thead = gview.find("table.ui-jqgrid-htable>thead"); mygrid.prepend(thead); $tr = $("<tr>"); for (i = 0; i < colModel.length; i++) { $th = $(ths[i].el); cmi = colModel[i]; if (cmi.name !== startColumnName) { if (skip === 0) { $th.attr("rowspan", "2"); } else { denySelectionOnDoubleClick($th); $th.css({"padding-top": "2px", height: "19px"}); $tr.append(ths[i].el); skip--; } } else { colHeader = $('<th class="ui-state-default ui-th-ltr" colspan="' + numberOfColumns + '" style="height:19px;padding-top:1px;text-align:center" role="columnheader">' + titleText + '</th>'); denySelectionOnDoubleClick($th); $th.before(colHeader); $tr.append(ths[i].el); skip = numberOfColumns - 1; } } mygrid.children("thead").append($tr[0]); };
In addition, some changes were required to the jqGrid code. You can download the modified version (modification of version 4.1.2) jquery.jqGrid.src.js from here . Changes consist of two blocks. First, I changed the code for the sortData function, lines 1874 - 1884
var thd= $("thead:first",ts.grid.hDiv).get(0); $("tr th:eq("+ts.p.lastsort+") span.ui-grid-ico-sort",thd).addClass('ui-state-disabled'); $("tr th:eq("+ts.p.lastsort+")",thd).attr("aria-selected","false"); $("tr th:eq("+idxcol+") span.ui-icon-"+ts.p.sortorder,thd).removeClass('ui-state-disabled'); $("tr th:eq("+idxcol+")",thd).attr("aria-selected","true"); if(!ts.p.viewsortcols[0]) { if(ts.p.lastsort != idxcol) { $("tr th:eq("+ts.p.lastsort+") span.s-ico",thd).hide(); $("tr th:eq("+idxcol+") span.s-ico",thd).show(); } }
to the next:
var previousSelectedTh = ts.grid.headers[ts.p.lastsort].el, newSelectedTh = ts.grid.headers[idxcol].el; $("span.ui-grid-ico-sort",previousSelectedTh).addClass('ui-state-disabled'); $(previousSelectedTh).attr("aria-selected","false"); $("span.ui-icon-"+ts.p.sortorder,newSelectedTh).removeClass('ui-state-disabled'); $(newSelectedTh).attr("aria-selected","true"); if(!ts.p.viewsortcols[0]) { if(ts.p.lastsort != idxcol) { $("span.s-ico",previousSelectedTh).hide(); $("span.s-ico",newSelectedTh).show(); } }
Next, I defined the getColumnHeaderIndex function as follows
var getColumnHeaderIndex = function (th) { var i, headers = ts.grid.headers, ci = $.jgrid.getCellIndex(th); for (i = 0; i < headers.length; i++) { if (th === headers[i].el) { ci = i; break; } } return ci; };
and changed lines 2172 and 2185 grid.base.js from
var ci = $.jgrid.getCellIndex(this);
to
var ci = getColumnHeaderIndex(this);
All. The above changes should not adversely affect jqGrid source code and can be used as usual. I will post my proposal next time on the trirand forum.
UPDATED : Another version of the demo allows you to resize all columns, except for columns that have headers. In the version, all columns on which an additional column heading will be placed should have the same width. Column widths are not automatically split between columns . You must set the same column width manually .
UDPATED 2 . I want to report on some progress in creating a more advanced version of multiheader jqGrid. The first wildraid published a very interesting solution. See His demo here . By the way, if you use the jqGrid method with the corrections that I proposed (see above), the problem with sorting the icons in the demo will be solved. See here for a demo as a conformation.
After that, I work a little more to reduce the limitations in my multi-column approach, which use rowSpan to increase the height of the columns. Here is my current interim result: a new demo . The new demo already works very well in Internet Explorer 9/8, Firefox, and Opera. In Webkit-based browsers (Google Chrome and Safari), it still contains the limitations listed above (column headings that have multiple headings should be the same size and not resize). The demo has well-preserved limitations, and it looks good in Webkit-based web browsers. However, you can see the progress in sorting.
I plan to increase the height of the resizing area used to resize columns based on the demo from. Because of this, the use of many headings over column headings will also be supported. ColumnChooser or showCol / hideCol are also supported. The most interesting thing for me now is to find a clear way to embed multirows column headers using rowSpan in Webkit-based browsers (Google Chrome and Safari). Probably someone will find a solution? This is the main reason why I decide to share the incomplete results here.
UPDATE 3 : changes to jqGrid code (see here ) in the main code from jqGrid are included. I improved the solution I described here in this and this demo. The second demo will increase the grid width if the column width is increased. I personally like the behavior.
UPDATE 4 . In the next version of the demo you can see here . It has a logical option ( useColSpanStyle parameter) that determines whether to use colspan or not. If false parameter will be as follows .