Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resizing window causes grid items to be positioned out of order #1975

Closed
harrington101 opened this issue Jun 7, 2022 · 11 comments · Fixed by #2088
Closed

Resizing window causes grid items to be positioned out of order #1975

harrington101 opened this issue Jun 7, 2022 · 11 comments · Fixed by #2088

Comments

@harrington101
Copy link

harrington101 commented Jun 7, 2022

Subject of the issue

Resizing window causes grid items to be positioned to the right. And order changes when resizing.

Your environment

  • Version 5.1
  • Chrome Windows 10

Steps to reproduce

I have 4 items that are 1 column wide followed by 2 items that are 4 columns wide. With the following settings, and the window set to less than 992px, there are 2 columns but the last 2 items that were in the first row on a large screen (when there were 4 columns) are now stacked in the right column under the first 2 items like so:
1 2
_ 3
_ 4
5
6

var grid = GridStack.init({
    column: 4,
    cellHeight: "140px",
    disableOneColumnMode: true,
    float: false,
    handle: ".tile__heading"
});

setTimeout(function () {
    resizeGrid();
}, 1000);

function resizeGrid() {
    let width = document.body.clientWidth;
    let layout = "moveScale";
    if (width < 576) {
        grid.column(1, layout);
    } else if (width < 992) {
        grid.column(2, layout);
    } else if (width < 1100) {
        grid.column(3, layout);
    } else {
        grid.column(4, layout);
    }
}

window.addEventListener('resize', function () { resizeGrid(); });

Expected behavior

The last 2 items in the first row should flow under the first 2 items like so:
1 2
3 4
5
6

Actual behavior

Instead they flow leaving 2 blank spaces on the left like so:
1 2
_ 3
_ 4
5
6

@harrington101
Copy link
Author

I enabled compact mode which sort of solves the issue, except when changing the screen size back the order of the items is different than it originally was. It seems that it starts as:
1, 2, 3, 4
Then becomes:
1, 2
4, 3
Then when grown again is:
4, 1, 3, 2

It should be 1, 2, 3, 4 or
1, 2
3, 4

@adumesny
Copy link
Member

can you post a running example (use bug template). thanks.

@harrington101
Copy link
Author

harrington101 commented Jun 16, 2022

Here is a sample of my code on JS Fiddle. You'll notice that as you resize the pane where the grid is that the numbers get out of order. Also, on page load, tile 9 shows up before tile 8. JSFiddle

@harrington101 harrington101 changed the title Resizing window causes grid items to be positioned to the right Resizing window causes grid items to be positioned out of order Jun 23, 2022
@adumesny
Copy link
Member

adumesny commented Jun 23, 2022

you need to reduce your example to just like the demos (init the grid with gs-x/gs-y values as html template, or load() with correct json) and not some convoluted template if you want me to take a look...

for one thing you have gs-x="0" gs-y="{{order}}" so they are all vertically placed and don't assume it will be this order as they have different real height, so when it comes to insert 9, it will be y LESS than actual 8 that was created (because things shift to fit for each element) which is why 9 is before 8 at the end. IFF you omit X or Y then it will be placed as the next open slot instead (what you want to create an ordered list).

Also, resizing the window will NOT in your case reflow the items as you and only you know that you have a 0-9 order list of items that fill the space. I suppose it would need a custom grid.column(x, 'list') kind of layout that keeps the items order the same and reflow is all each time, which we don't support, but could for the right donation.

@harrington101
Copy link
Author

harrington101 commented Jun 27, 2022

Unfortunately I can't save the X and Y position in the database because the X and Y position is different depending on the screen size which controls the number of columns shown (1 on mobile, 2 on tablet, 3 on small desktop, 4 on large desktop). I did create a function called update positions that might be helpful. It loops through a presorted array of objects and finds the next available position that the item will fit in. I run this on page load and any time the screen or layout div changes size. An issue my code has at the moment is that if someone stacks two 1h tiles next to a 2h tile it doesn't preserve that stack. I am OK with preventing stacking if that is a setting somewhere.

Here is my helper function:

var tileSettings = [
{order: 0, title: "tile 1", colSpan: 1, rowSpan: 1, id: "tile1"}, 
{order: 1, title: "tile 2", colSpan: 1, rowSpan: 2, id: "tile2"},
{order: 1, title: "tile 3", colSpan: 1, rowSpan: 1, id: "tile3"},
];
function updatePositions() {
        tileSettings = sortObjectArray(tileSettings, "order");
        let newY = 0;
        let newX = 0;
        let rowHeight = 1;
        let columns = grid.getColumn();
        $.each(tileSettings, function (index, item) {
            if (item.colSpan > columns || newX + item.colSpan > columns) {
                newX = 0;
                newY = newY + rowHeight;
            }
            grid.update(`#tile_${tileSettings[index].id}`, { x: newX, y: newY });
            if (rowHeight < item.rowSpan) {
                rowHeight = item.rowSpan;
            }
            if (newX + item.colSpan >= columns) {
                newX = 0;
                newY = newY + rowHeight;
                rowHeight = 1;
            } else {
                newX = newX + item.colSpan;
            }
        });
    }

@adumesny
Copy link
Member

| I did create a function called update positions that might be helpful. It loops through a presorted array of objects and finds the next available position that the item will fit in.

that sounds like the compact() method that already exists.

I'll be closing this without a simple example of what you need showing either a bug or a feature request (with corresponding donations to make it happen)...

@harrington101
Copy link
Author

This is actually different from compact(). I tried that one but it caused all of the tiles to be rearranged in an arbitrary order. This preserves the tiles in the original order.

@adumesny
Copy link
Member

ok, true it tries to fill any empty spot (hence the name) - could be an optional arg to keep order the same, or a different method altogether.

@doktordirk
Copy link

could be related, but there's a bug in the code for sorting

where it says in updateNodeWidths

// finally re-layout them in reverse order (to get correct placement)
 newNodes = utils_1.Utils.sort(newNodes, -1, column); 

should be instead, so that oneColumnModeDomSort: true, get's respected

// finally re-layout them in reverse order (to get correct placement)
 if (!domOrder) newNodes = utils_1.Utils.sort(newNodes, -1, column); 

@jjdinho
Copy link

jjdinho commented Jul 22, 2022

Responding to the above comment:

could be related, but there's a bug in the code for sorting

I am experiencing a similar bug related to oneColumnModeDomSort: true - it seems this option is not being respected if the grid is initialized in oneColumnMode and the HTML GridStackElements have gs-x and gs-y attributes. It seems that these attributes are used even if they should be ignored because oneColumnModeDomSort: true.

However, sorting works as expected if the grid is initialized on a large screen (not using oneColumnMode) and then resized so that oneColumnMode kicks in.

I know this is departing perhaps from the original bug, but wanted to get a reply in here as the above comment seemed appropriate.

@adumesny
Copy link
Member

fixing @doktordirk and @jjdinho bug above in next release, closing the remaining issue as not explicit about what needs to be long and too convoluted. @harrington101 if you need this fixed file a very simple separate bug again

adumesny added a commit to adumesny/gridstack.js that referenced this issue Oct 23, 2022
fix gridstack#1985
fix gridstack#1975 (oneColumnModeDomSort case)

* we now handle DOM and addWidget() when temporally into 1 column mode better to save the full 12 column mode
* also DOM reading will reverse-sort entries to lay them in 1 column mode correctly (like if you had started with 12 and scaled down)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants