SlickGrid 样式在 JQueryUI Accordion 和 Bootstrap框架的兼容性解决办法

SlickGrid with jQueryUI and Bootstrap


原文地址:http://low-bandwidth.blogspot.com.au/2015/06/slickgrid-with-jqueryui-and-bootstrap.html

Recently I've taken up the mantle of maintaining an updated fork of MLeibman's fantastic SlickGrid trunk. I suppose it was inevitable that it would lead to a blog post.

There have been multiple issues posted about the jQuery Accordion and about Bootstrap 3 issues with sizing. After examination, the bootstrap issue is quite complex and I thought it was worth documenting the details of both.
The first step was to add stripped down, simple example pages for both cases to be used for testing.  example-jquery-accordion.html and example-bootstrap-3-header.html are now present in the examples folder of my  alternative master repository.

Accordion Formatting

The formatting of the SlickGrid header row was showing small inconsistencies in header size:








This was a minor CSS issue: it appears that in normal situations the header is formatted by the 
.slick-header-column.ui-state-default class, which is being evaluated as more specific than (hence takes precedence over) the generic jQueryUI ui-state-default class.
When enclosed in the accordion div (and I'd assume tabs or any other similar container),  ui-state-default gets precedence and adds extra border segments.
It is easily fixed by adding the  !important tag to various SlickGrid header classes. This is exactly the kind of situation that  !important is designed for.

.slick-header.ui-state-default, .slick-headerrow.ui-state-default {
  width: 100%;
  overflow: hidden;
  border-left: 0px !important;
}
.slick-header-column.ui-state-default {
  position: relative;
  display: inline-block;
  overflow: hidden;
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
  height: 16px;
  line-height: 16px;
  margin: 0;
  padding: 4px;
  border-right: 1px solid silver;
  border-left: 0px !important;
  border-top: 0px !important;
  border-bottom: 0px !important;
  float: left;
}

Blank Grid Display in Accordion in IE8

More sinister was a problem with vanishing grid contents. I tested in IE8 but other IE versions may also be implicated.
Steps to reproduce using the accordion demo page:
1) open the page in IE 8 and scroll the first grid down a page or so.
2) switch to the second accordion, then back
The first grid should now be blank.

This is an IE rendering issue - IE resets the scrollbar and display when a div or its parent is hidden with  display:none. Checking it out with the IE developer tools showed that the DOM elements still existed, but just weren't being shown. Probably because of this, all attempts to refresh the grid failed. Only destroying and recreating the grid was able to get past the blank display.

Because this workaround changes the screen UI, I have commented the code out in the demo page, but it is there if needed.
I was unable (and frankly unwilling) to find a solution for what appears to be an IE bug. If anyone finds a mechanism for refreshing the blank div, let me know and I'll bake it in to the grid.

Bootstrap 3 Column Width Issues

There have been many reports of column width issues under Bootstrap 3. It doesn't take long to find the culprit. Simply including the bootstrap.css file on your page includes this little gem:

* {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}
*:before,
*:after {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

Admittedly, border-box is a much more sensible model, but this css forces  border-box onto most elements on the page (some inputs are excluded).
The interesting thing is that the main (MLeibman) branch of SlickGrid, which is at jQuery 1.7, deals with this perfectly. The header height needs css tweaking, but the column widths resize and drag fine. It's only after we update jQuery that the trouble starts.

The problem is similar to the first image, but it only starts when resizing columns. The drag handle and column header size are offset by an amount equal to the padding and border widths of the column. Worse, the effect is cumulative each time the column is resized.

The reason is summarised  here (thanks to  JCReady for the heads up). The way jQuery handles  box-sizing: border-box in relation to the .width and .outerWidth properties changed in jQuery 1.8. Before, .width essentially did a .css("width") which meant that it would return different numbers depending on the  box-sizing setting. Afterwards, it returned the correct inner element size regardless of the  box-sizing setting (note that it warns of the performance hit for this feature).
1.8 also allowed .outerWidth to be used as a setter.

Solution 1

A very easy (and tempting) solution is to follow in the footsteps of the css fixes above and add:

slick-header-column.ui-state-default {
   box-sizing: content-box !important;
}

This works just fine since the existing codebase was written to use the default  box-sizing: content-box setting. However, it is conceivable that border-box could be needed on the header elements, particularly when using the menu and button features that are available. I resolved to rather solve the problem in the code.

Solution 2

Most of the forum fixes for the column sizing issue recommend replacing all occurences of  .width with  .outerWidth. This works for the   box-sizing: border-box case but manifests a mirror image problem with  content-box (ie. the offset is negative instead of positive).
In order to preserve the correct operation under the old and new jQuery versions in both   box-sizing cases, it was necessary to sniff the jQuery version and provide an alternate code path.
In the end, it was only necessary to make a small adjustment to  applyColumnHeaderWidths to solve the issue.
See the  commit for code details.

6 comments:

  1. Leonardo Trimarchi June 3, 2015 at 10:22 PM

    Youre the man! Will keep you updated on if the change works. Thank you

    ReplyDelete
  2. Ben McIntyre June 4, 2015 at 10:32 AM

    Thanks! I have been testing on Chrome and IE8, but testing on a bigger range of browsers would be a bonus.

    ReplyDelete
  3. Technews Able August 5, 2015 at 12:19 PM

    What is bootstrap and why should you use bootstrap?

    ReplyDelete
  4. Unknown September 30, 2015 at 10:53 AM

    Hello Ben. Great Work. in "slick.grid.js" file, around line 925 where you are checking new jQuery behavior, you only check if major is >=1 and minor >=8, so it will not work if minor release is less than 8, but major release is more than 1, i.e. 2.1.1 etc.

    For my code, I added the 3rd line below:
    var verArray = $.fn.jquery.split('.');
    jQueryNewWidthBehaviour = verArray[0]>=1 && verArray[1]>=8;
    jQueryNewWidthBehavior = verArray[0] >=2 ; //if jquery version is 2 or more , its automatically greater than 1 :)

    ReplyDelete
  5. Ben McIntyre September 30, 2015 at 7:21 PM

    good catch. however, I think your new code line code overwrites the value from the previous line!
    you should use |=, or use an or || clause to join it to the first line.
    anyway, I'll patch the repo right now.

    ReplyDelete
  6. Ben McIntyre September 30, 2015 at 7:24 PM

    jQueryNewWidthBehaviour = (verArray[0]==1 && verArray[1]>=8) || verArray[0] >=2;

    ReplyDelete
Add comment
Load more...

你可能感兴趣的:(MVC,jQuery)