tiberiuzuld / angular-gridster2

Angular gridster 2

Home Page:https://tiberiuzuld.github.io/angular-gridster2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Crash when resizing grid item

dzhavat opened this issue · comments

Hi Tiberiu,

First of all thank you for taking the time to work on this library. It works really well. I use it in one web app I'm working on.

Recently I encountered a small bug when resizing a widget. Here's my use case:
I have a widget with an iframe inside. When I start resizing the widget everything works fine but if I release the mouse over the iframe the code breaks and from then on the widget sticks to the mouse movement and keeps following. The error is shown after clicking again the edges of the widget.

I made a small gif to illustrate the problem:

problem

This error might be related to #214 somehow.

Thanks for your help!

Hi @dzhavat ,
What version of the library do you use ?
What version of angular do you use ?

The demonstration is from the live demo so I assume you're using the latest of both Angular and the library. You can try it as well. Just copy any iframe (eg. a YouTube embed) and paste it as HTML in one of the widgets. Then try resize that widget.

Otherwise in my project I use "angular-gridster2": "3.11.5" and "@angular/core": "5.2.0"

So I did managed to reproduce the issue with an iFrame.
The mouse events from inside the iframe are not propagated to the parent document.
This is how browsers work. Nothing we can do to change that.

Unfortunately there is nothing I can do. But there is something you can do.
Here's a work around I read here :
With drag/resize start callback you can hide the iframe or place a transparent div over the iframe.
With drag/resize stop callback you can do the reverse thing.

This should solve your issue.

Or got another idea to have a transparent div always over the iframe and by default to have pointer-events none and when drag/resize occurs set pointer events to initial.
You can do this easily by just setting a class on the div.

You should have this on all widgets with iframe even if you drag/resize only one widget.

gridster-item .my-div {
 pointer-events: none;
}

.my-drag-in-progress gridster-item .my-div {
 pointer-events: initial;
}

The mouse events from inside the iframe are not propagated to the parent document.
This is how browsers work. Nothing we can do to change that.

Yeah, that's right.

With drag/resize start callback you can hide the iframe or place a transparent div over the iframe.

Adding a transparent div over the iframe was suggested by a colleague of mine as well but we haven't tried it yet. Maybe we can give it a shot and see if that will help with our case.

Thanks for the ideas. Will get back with more info once I have some results :)

I will assume this issue is fixed.

I have this issue of a drag starting to follow mouse-cursor also. But in my case it has nothing to do with iframe, because I have none on my gridster-app. Instead, what I have found that causes this issue for me, is that when ever during or at the end of dragging any text-content gets selected (and it easily often does), and when you start then the next drag-operation with the same drag-item (on which content-text is still selected), the issue start appearing (i.e drag-item follows cursor and the console logs the same error "...Cannot read property 'setPushedItems' of undefined..."). However, before a new drag, if I with the extra mouse-click upon the drag-item unselect the selected text-content, issue never seems to appear. As a further observation, if text-content is selected on a drag-item, the drag-operation does not start dragging the actual drag-item but the selected text-content instead. Any idea how to solve this issue?

the problem with this if you have content that can be clicked inside the iframe ? if you do pointer-events: none; then you won't be able to fire click event inside the iframe. is there a work around ?

I fixed the 'setPushedItems' error this way using @tiberiuzuld comment above:

gridster-item .iframe-container {
    pointer-events: initial;
}

.gridster-item-moving .iframe-container {
    pointer-events: none;
}

.gridster-item-resizing .iframe-container {
    pointer-events: none;
}
<gridster [options]="options" height="900px" width="100%">
    <gridster-item [item]="item" *ngFor="let item of dashboard">
        <div class="iframe-container">
            <iframe id="iframe" [src]="computeUrl() | safe" frameborder="0" style="" height="900px" width="100%">
            </iframe>
        </div>
    </gridster-item>
</gridster>

this solution is not valid, for some reasons it looks like it is still in resize/draggable mode sometimes even though you release the mouse key up , you need to click with your mouse left button once again to remove the resize/draggable state

I fixed the 'setPushedItems' error this way using @tiberiuzuld comment above:

gridster-item .iframe-container {
    pointer-events: initial;
}

.gridster-item-moving .iframe-container {
    pointer-events: none;
}

.gridster-item-resizing .iframe-container {
    pointer-events: none;
}
<gridster [options]="options" height="900px" width="100%">
    <gridster-item [item]="item" *ngFor="let item of dashboard">
        <div class="iframe-container">
            <iframe id="iframe" [src]="computeUrl() | safe" frameborder="0" style="" height="900px" width="100%">
            </iframe>
        </div>
    </gridster-item>
</gridster>

Thanks @ecenedis this fixed my issue.

Hi I have tried using the above suggested solution but its not working.

Please find below the stackblitx link for the same
https://stackblitz.com/edit/angular-8-app-example-mwtprp?file=src/app/app.component.css

Extra note on @ecenedis solution:
Solution to add pointer-events: none; does solve the issue when we resize iframe container but issue might still occur if you resize a non-iframe container and release the cursor above the iframe.

The complete solution will be to add pointer-events: none to all iframe-containers when resizing any of the gridster-item.

@rahultokase The issue you are facing is the same as I described above. With the @ecenedis solution, the iframe container you are resizing have pointer-events: none during resize but the other iframe element doesn't thus causing the issue.

I wasn't able to find any CSS solution for this, so went with the following

// Define boolean variables gridsterItemResizing and gridsterItemDragging in the component and use the start & stop callback to update these variables
this.options = {
    draggable: {
        start: () => { this.gridsterItemDragging = true; },
        stop: () => { this.gridsterItemDragging = false; }
    },
    resizable: {
        start: () => { this.gridsterItemResizing = true; },
        stop: () => { this.gridsterItemResizing = false; }
    },
}

// In the component's CSS file define the following style
.disable-pointer-events {
    pointer-events: none;
}

// In the component's HTML file add the `disable-pointer-events` class to iframe container when we are resizing or dragging any gridster-item
<div [class.disable-pointer-events]="gridsterDragging || gridsterResizing" class="layout-container">
    <!-- Iframe container -->
</div>

Or got another idea to have a transparent div always over the iframe and by default to have pointer-events none and when drag/resize occurs set pointer events to initial.
You can do this easily by just setting a class on the div.

You should have this on all widgets with iframe even if you drag/resize only one widget.

gridster-item .my-div {
 pointer-events: none;
}

.my-drag-in-progress gridster-item .my-div {
 pointer-events: initial;
}

Thank You bro It's work for me :)