jqGrid does not render correctly in Chrome/Chrome

2019-01-01 03:53发布

问题:

Currently using Chrome v19.0.1084.46 (Official Build 135956) beta-m jqGrid 4.3.2 (latest release)

The problem is that no matter the size of my grid, columns, or containing div, a small fraction of my last column gets pushed beyond the edge of the grid, causing horizontal scroll bars to appear, which should not happen. See below:

\"grid\"

I\'ve been fiddling with the following attributes on jqGrid to try and fix this:

  • width
  • autowidth
  • height
  • shrinkToFit
  • scrollOffset - Had the best luck with this one, but nothing repeatable.

I\'ve also stripped down to the basic grid css only, thinking it might have been a rule I put in place...with no luck.

Has anyone else experienced this and/or found a solution to this? Help is much appreciated.

回答1:

I updated today my Chrome to version 19, have reproduced the problem and made the corresponding quick&dirty fix:

I suggest to change the line of jqGrid code

isSafari = $.browser.webkit || $.browser.safari ? true : false;

to the following

isSafari = ($.browser.webkit || $.browser.safari) &&
    parseFloat($.browser.version)<536.5 ? true : false; // Chrome < version 19

The demo use the fix. The fixed version of jquery.jqGrid.src.js which I used in the demo you can get here.

I tested it in IE9 (v9.0.8112.16421), IE8 (8.0.6001.18702CO), Chrome 18.0.125.168, Chrome 19.0.1084.46, Safari 5.1.7 (7534.57.2), Firefox 12, Opera 11.62. In all the web browsers the demo has no horizontal scrollbars and it looks as following:

\"enter

In the future it would be better to change the calculation of width of the grid more deep to have no direct dependency from any version number or web browser. I hope it will be possible if one would use more jQuery methods $.width and $.outerWidth in some places of jqGrid. In any way I hope that the above described fix would be already helpful for many jqGrid users.

UPDATED: I posted my suggestion to trirand as the bug report.

UPDATED 2: To be exactly there are three places in the code where are used the same $.browser.webkit || $.browser.safari construct as described above: inside setGridWidth, inside of getOffset, inside of calculation of the width of multiselect column, inside showHideCol and inside setGridWidth. The first three places uses isSafari variable. The last two places uses $.browser.webkit || $.browser.safari directly. One should replace in all the places the code

$.browser.webkit||$.browser.safari

to

($.browser.webkit || $.browser.safari) && parseFloat($.browser.version)<536.5

So one should do this in three places:

  1. at the definition of the isSafari (see me original post)
  2. inside of showHideCol
  3. inside of setGridWidth

You can download the fixed version of the jquery.jqGrid.src with all the fixes here. You can make the same changes in the code of jquery.jqGrid.src yourself if you have to use old version of jqGrid. To created minimized version for the production you can use any minimizer which you good know. I use for example Microsoft Ajax Minifier 4.0. Just install it and execute

AjaxMin.exe jquery.jqGrid.src-fixed3.js -o jquery.jqGrid.min-fixed3.js

As the result you will get jquery.jqGrid.min-fixed3.js which will be even smaller as original jquery.jqGrid.min.js. Even if you add the comment header to the file (see modified file) the file will be still smaller as original version of jquery.jqGrid.min.js.

After some iterations of my bug report and the improvements there are one more version of the fix where the method cellWidth was introduced:

cellWidth : function () {
    var $testDiv = $(\"<div class=\'ui-jqgrid\' style=\'left:10000px\'><table class=\'ui-jqgrid-btable\' style=\'width:5px;\'><tr class=\'jqgrow\'><td style=\'width:5px;\'></td></tr></table></div>\"),
        testCell = $testDiv.appendTo(\"body\")
            .find(\"td\")
            .width();
        $testDiv.remove();
        return testCell !== 5;
}

See here. If you prefer to follow the way you can do this also. In the case in all places where isSafari or $.browser.webkit || $.browser.safari (in showHideCol and setGridWidth) are used you can use $.jgrid.cellWidth() instead.

UPDATED 3: Today was published jqGrid 4.3.3 which contains the fix which I described above (the cellWidth method). So I recommend all to use the new version.

UPDATED 4: Google Chrome 20 uses WebKit 536.11. So everybody who can\'t use the last version of jqGrid with the fixed calculation of the width should use parseFloat($.browser.version)<536.11 (or some close) instead of parseFloat($.browser.version)<536.5 described at the beginning of the answer. Google Chrome 23 WebKit uses 537.11.



回答2:

Oleg\'s solution worked for me.

I just edited the min version

line 49:

replaced:

m=b.browser.webkit||b.browser.safari?!0:!1

with:

m=(b.browser.webkit||b.browser.safari)&&parseFloat(b.browser.version)<536.5?!0:!1

Thanks for the help!



回答3:

Oleg\'s answer is correct. However, if you are using an older version of jqGrid and want to apply these fixes, it may be easier to take the changes directly from the diffs on Github. I have tested this successfully using jqGrid 4.0.0, so presumably it will work on any of the 4.x series.

Just start with the first diff and apply each of them in order. This will add the cellWidth function and make all of the necessary changes across the jquery.jqGrid.src.js file. Then you can use the Google closure compiler if you want to create a minified version:

  • 8c56dc8
  • b50b55f
  • cf26b2c
  • 8d7eff0
  • 46a14ce

It seems like a lot of changes, but when you look at the actual code the changes will go very quickly. Only a few source lines are affected.



回答4:

Chrome beta 20.0.1132.11 is out and reports the following:

User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 Safari/536.11

I am guessing 536.11 is evaluating as < 536.5 due to numeric vs text comparison causing the patch not to be operative?

Please help!



回答5:

Update: My anwswer refers to a similar issue that happened in Firefox a few months ago and I suggested in hopes that it would work for Chrome 19, but currently Oleg\'s answer is the correct approach.

I had a similar issue a few months ago with FF and I was using the ForceFit option which should disable the HScroll entirely but like you mentioned I would still get it so I just disabled the HScroll for my forcefit grids. A few updates later of FF, it did stop happening, and currently all of my grids are fine in Chrome 18 so hopefully it will not be an issue when 19 is released.

//remove HScroll
function jqGridDisableHScroll(gridid) {
    //if columns are force fit all columns will always fit on screen.
    if ($(\'#\' + gridid).jqGrid(\'getGridParam\', \'forceFit\')) {
        var gridview = $(\'#gview_\' + gridid);
        $(\'.ui-jqgrid-bdiv\', gridview).css({ \'overflow-x\': \'hidden\' });
    }
}

Force Fit

If set to true, and resizing the width of a column, the adjacent column (to the right) will resize so that the overall grid width is maintained (e.g., reducing the width of column 2 by 30px will increase the size of column 3 by 30px). In this case there is no horizontal scrolbar. Note: this option is not compatible with shrinkToFit option - i.e if shrinkToFit is set to false, forceFit is ignored.



回答6:

Just wanted to point out that this is likely due to webkit issue 78412 finally being resolved. Essentially it would not account for borders, and I believe the padding as well, when calculating the width of tables with a fixed layout.

This meant that jqGrid would incorrectly calculate the width of the table as only the width of its content area. So removing the borders and padding should also solve the problem, but you probably wouldn\'t want to do that.



回答7:

We use jgGrid 4.3.3 and cellWidth didn\'t solve the issue...in order to solve it, I added the line return parseInt(testCell) !== 5; instead return testCell !== 5; in cellWidth method. Maybe it\'s not the best solution, but it works for us :)



回答8:

In jQGrid 4.5.2 with Chrome 59.0.3071.115 I changed the cellWidth function in grid.base.js to:

 return Math.round(testCell) !== 5