Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jqGrid - Dragging a row to sort it screws up cell widths

My problem: When I drag a row in jqGrid, and it completes a custom reload function, the cells of the grid, previously all of varying widths set when the grid is defined, are resized to all be the same width. This happens in Webkit browsers but not in Firefox.

Code: I have dragging to sort enabled on a grid:

$mygrid.jqGrid(
    'sortableRows', {
        update: function(e, ui) {
            sort_grid(e, ui);
        }
    }
);

As you can see I have a sorting function called on drag complete, sort_grid. Here it is:

function sort_grid(e, ui) {
    var current_grid = $(ui.item[0]).closest('table').attr('id');
    var $current_row, moved_id, next_id, next_priority;
    var $moved_row = $('#' + current_grid + ' tr');
    var cnt = 0;

    this_id = ui.item[0].id;
    $moved_row.each(function () {
        if ($(this).attr('id') == this_id) {
            $current_row = $moved_row.eq(cnt);
            moved_id = $current_row.attr("id");
            next_id = $current_row.next().attr("id");
            next_priority = $current_row.next().children("td:first").attr("title");
        }
        cnt++;
    });

    if ( typeof moved_id !== 'undefined' ) {
        if ( next_priority == 'undefined' ) {
            next_priority = '999';
        }

        $.ajax({
            url:my_url,
            type:"POST",
            data:"moved_id=" + moved_id + "&next_id=" + next_id + "&next_priority=" + next_priority,
            success: function(data) {

                $('.grid').setGridParam({loadonce:false, datatype:'json'}); // force grid refresh from server
                $('#' + current_grid).trigger("reloadGrid");
                $('.grid').setGridParam({loadonce:true}); // reset to use local values

            }
        })
    }
}

Once I hit that reload trigger $('#' + current_grid).trigger("reloadGrid"); and reload finishes the grid now has incorrect widths on the cells in the grid (they go from being of various widths to all being the same width).

When the grid was originally created it had widths defined in the normal jqGrid fashion:

colModel:[
    {name:'one', index:'one', sortable:true, width:45},
    {name:'two', index:'two', sortable:true, width:180},
]

but after the grid reload the widths are reset all be the same width (I assume this is the total width of the grid being evenly divided over the total number of cells in the row). So, do I need to explicitly set these widths again, perhaps with something like the following called after the grid reloads?

$('.grid').setGridParam({
    colModel:[
        {name:'one', index:'one', sortable:true, width:45},
        {name:'two', index:'two', sortable:true, width:180},
    ]
});

I tried the above fix, redefining the colModels after reload and explicitly setting the widths, but it had no effect. Weirder, if I go into the browser console and set the widths with javascript it also has no effect. That's got me stumped.


Unfortunately for me it looks like the jqGrid "Answer Man" (Oleg) is not around... lol.

like image 987
Lothar Avatar asked Feb 09 '12 00:02

Lothar


1 Answers

I faced the same problem for Chrome. I recreated it here http://jsfiddle.net/gZSra/. Just drag the row and then sort any column.

But after few hard hours of debugging jqGrid sources I finally fixed this bug. The problem appears in emptyRows method of jqGrid.

emptyRows = function (scroll, locdata) {
    var firstrow;
    if (this.p.deepempty) {
        $(this.rows).slice(1).remove();
    } else {
        firstrow = this.rows.length > 0 ? this.rows[0] : null;
        $(this.firstChild).empty().append(firstrow);  // bug "activation" line 
    }
    if (scroll && this.p.scroll) {
        $(this.grid.bDiv.firstChild).css({height: "auto"});
        $(this.grid.bDiv.firstChild.firstChild).css({height: 0, display: "none"});
        if (this.grid.bDiv.scrollTop !== 0) {
            this.grid.bDiv.scrollTop = 0;
        }
    }
    if(locdata === true && this.p.treeGrid) {
        this.p.data = []; this.p._index = {};
    }
},

*In recent jqGrid-4.4.4 this code begins from 1070 line of jqGrid.src.js

The problem connected removing and then appending firstrow. This row defines width of columns - one of it's cells in my jsFiddle example is

<td role="gridcell" style="height:0px;width:60px;"></td>

That is why problem seems to be connected with some Chrome's or Webkit's dynamic table behaviour.

FIX

Replace infected else scope with next line

$(this.firstChild).find('tr:not(:first)').remove();

It's not hard to see that instead of removing all lines and then appending first back, I just selecting and removing all except first row.

Result jsFiddle: http://jsfiddle.net/HJ3Q3/

Tested in Chrome, FF, IE 8 & 9.

Hope this fix will soon become part of jqGrid sources.

like image 171
PokatilovArt Avatar answered Oct 27 '22 00:10

PokatilovArt