oria / gridx

Just another powerful Dojo grid
Other
162 stars 78 forks source link

IndirectSelect with extendedSelect/Row alignment issues in Chrome #403

Open vshmelev opened 7 years ago

vshmelev commented 7 years ago

Hi, I modified test_grid_indirectSelect and remove paging to show all result items in grid on one page with scrolling. And in Chrome (only, IE and FF seems to be OK) selection boxes on the left get out of alignment with the corresponding lines. Please see attached screenshot. Any good solution for this issue? Thanks! gridx-select-issue

vshmelev commented 7 years ago

Providing modified test_grid_indirectSelect.html just in case: test_grid_indirectSelect_modified.html.txt

blueleader07 commented 7 years ago

+1 I am also seeing this issue in Chrome. Any idea if there is a workaround? Or a fix coming?

blueleader07 commented 7 years ago

Here's what I did to work around the issue. It works for us, but might not work for everyone.

The row heights are set in gridx/modules/RowHeader.js, specifically the _syncRowHeight function.

In our case, we had (long ago) styled the row height using a CSS class. You might have a different style... or no style at all. I'm just pointing this out so you understand where I get the heights from in my version of the _syncRowHeght function below. Here is our CSS style:

.claro .gridxRow .gridxRowTable {
    height: 25px;
}

I have a utility class called GridXUtils that I've used to work around other issues. I created a function to replace the _syncRowHeight function:

//https://github.com/oria/gridx/issues/403
fixChromeAlignmentIssue: function(grid){
    grid.rowHeader._syncRowHeight = function(rowHeaderNode, bodyNode){
        //Check if the table is collasped.
        var t = this, h, isIE = has('ie'), isChrome = has('chrome');

        //ADDED THIS TO FIX CHROME ALIGNMENT - Sean McKeon
        var browserZoomLevel = Math.round(window.devicePixelRatio * 100);

        if (t._isCollapse === undefined) {
            var refNode = query('.gridxCell', t.grid.header.innerNode)[0];
            t._isCollapse = refNode && domStyle.get(refNode, 'borderCollapse') == 'collapse';
        }
        //Use setTimeout to ensure the row header height correct reflects the body row height.
        //FIXME: This is tricky and may not be working in some special cases.
        function getHeight(){
            return has('ie') <= 8 || t._isCollapse ? bodyNode.offsetHeight + 'px' : domStyle.getComputedStyle(bodyNode).height;
        }
        //ADDED THIS TO FIX CHROME ALIGNMENT - Sean McKeon
        var rowHeaderHeights = [];
        rowHeaderHeights[110] = '24.5px';
        rowHeaderHeights[125] = '24.8px';
        rowHeaderHeights[150] = '24.6px';
        rowHeaderHeights[175] = '24.5px';
        function calculateRowHeaderHeight(bodyNode, browserZoomLevel){
            var rowHeaderHeight = rowHeaderHeights[browserZoomLevel];
            return rowHeaderHeight || bodyNode.firstChild.clientHeight + 1 + 'px';
        }
        setTimeout(function() {
            h = getHeight();
            if ((h + '').indexOf('.') >= 0) {
                if (isIE === 9) {
                    rowHeaderNode.style.height = rowHeaderNode.firstChild.style.height = bodyNode.style.height = bodyNode.clientHeight + 1 + 'px';
                } else {
                    if(isChrome){
                        //ADDED THIS TO FIX CHROME ALIGNMENT - Sean McKeon
                        rowHeaderNode.style.height = calculateRowHeaderHeight(bodyNode, browserZoomLevel);
                    } else {
                        rowHeaderNode.style.height = rowHeaderNode.firstChild.style.height = bodyNode.firstChild.style.height = bodyNode.firstChild.clientHeight + 1 + 'px';
                    }
                }
                //For IE,setting fixed height on row will break DOD.
                // bodyNode.style.height = '';
            } else {
                // rowHeaderNode.style.height = rowHeaderNode.firstChild.style.height  = h;
                if(rowHeaderNode && rowHeaderNode.firstChild){
                    rowHeaderNode.style.height = rowHeaderNode.firstChild.style.height = h;
                }
            }
        }, 0);
    };
}

I call this utility function just after the grid is created, but before startup:

var grid = new Grid({
    id: gridId,
    cacheClass: Cache,
    store: store,
    structure: getLayout(),
    selectRowTriggerOnCell: true,
    modules: [
        NestedSort,
        ColumnResizer,
        Filter,
        FilterBar,
        HiddenColumns,
        Menu,
        selectRow,
        rowHeader,
        IndirectSelect,
        moveColumn,
        dndColumn,
        selectColumn,
        selectCell,
        virtualVScroller,
        hscroller
    ],
    filterBarCloseButton: false,
    filterBarItemsName: "items",
    filterBarMaxRuleCount: 5,
    filterBarRuleCountToConfirmClearFilter: 999,
    bodyEmptyInfo: "No items were found for the selected criteria."
});
GridXUtils.fixChromeAlignmentIssue(grid);
grid.placeAt(gridContainerNode);
grid.startup();

As you can see I've got some hard-coded pixels in my version of the function. This works for me because I'm using a 25px height. You might have to play with the heights a bit to get it to work correctly for you. The alignment is not perfect... but it's pretty good. Good enough until this issue can be fixed by the GridX team.

jsonn commented 7 years ago

Can you try #365?

blueleader07 commented 7 years ago

365 did not seem to resolve my issue. However, while testing #365 I found I could simplify my fixChromeAlignmentIssue workaround ... no need to hard-code the pixels.

It seems that when getHeight() returns a decimal, for example "24.8px" the logic takes it down one path that does not seem to work in Chrome in some zoom scenarios. I've adjusted the logic to ALWAYS go into the ELSE if Chrome is detected. Alignment seems to work fine that way.

//https://github.com/oria/gridx/issues/403
fixChromeAlignmentIssue: function(grid){
    grid.rowHeader._syncRowHeight = function(rowHeaderNode, bodyNode){
        //Check if the table is collasped.
        var t = this, h, isIE = has('ie'), isChrome = has('chrome');

        if (t._isCollapse === undefined) {
            var refNode = query('.gridxCell', t.grid.header.innerNode)[0];
            t._isCollapse = refNode && domStyle.get(refNode, 'borderCollapse') == 'collapse';
        }
        //Use setTimeout to ensure the row header height correct reflects the body row height.
        //FIXME: This is tricky and may not be working in some special cases.
        function getHeight(){
            return has('ie') <= 8 || t._isCollapse ? bodyNode.offsetHeight + 'px' : domStyle.getComputedStyle(bodyNode).height;
        }
        setTimeout(function() {
            h = getHeight();
            //Adding isChrome check to fix Chrome Alignment issue (#403) - Sean McKeon
            if (!isChrome && (h + '').indexOf('.') >= 0) {
                if (isIE === 9) {
                    rowHeaderNode.style.height = rowHeaderNode.firstChild.style.height = bodyNode.style.height = bodyNode.clientHeight + 1 + 'px';
                } else {
                    rowHeaderNode.style.height = rowHeaderNode.firstChild.style.height = bodyNode.firstChild.style.height = bodyNode.firstChild.clientHeight + 1 + 'px';
                }
                //For IE,setting fixed height on row will break DOD.
                // bodyNode.style.height = '';
            } else {
                // rowHeaderNode.style.height = rowHeaderNode.firstChild.style.height  = h;
                if(rowHeaderNode && rowHeaderNode.firstChild){
                    rowHeaderNode.style.height = rowHeaderNode.firstChild.style.height = h;
                }
            }
        }, 0);
    };
}