Skip to content

Commit 0903d03

Browse files
authored
Merge pull request #2014 from adumesny/master
drag & drop Desktop nested fixes
2 parents db1b3cb + e829f3e commit 0903d03

File tree

5 files changed

+51
-41
lines changed

5 files changed

+51
-41
lines changed

src/dd-draggable.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
163163
} else if (Math.abs(e.x - s.x) + Math.abs(e.y - s.y) > 3) {
164164
/**
165165
* don't start unless we've moved at least 3 pixels
166-
*/
166+
*/
167167
this.dragging = true;
168168
DDManager.dragElement = this;
169169
// if we're dragging an actual grid item, set the current drop as the grid (to detect enter/leave)
@@ -179,7 +179,6 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
179179
const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'dragstart' });
180180

181181
this._setupHelperStyle(e);
182-
this.helper.classList.add('ui-draggable-dragging');
183182
if (this.option.start) {
184183
this.option.start(ev, this.ui());
185184
}
@@ -205,7 +204,6 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
205204
delete DDManager.dropElement;
206205
}
207206

208-
this.helper.classList.remove('ui-draggable-dragging');
209207
this.helperContainment.style.position = this.parentOriginStylePosition || null;
210208
if (this.helper === this.el) {
211209
this._removeHelperStyle();
@@ -250,10 +248,11 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
250248

251249
/** @internal set the fix position of the dragged item */
252250
protected _setupHelperStyle(e: DragEvent): DDDraggable {
251+
this.helper.classList.add('ui-draggable-dragging');
253252
// TODO: set all at once with style.cssText += ... ? https://stackoverflow.com/questions/3968593
254253
const style = this.helper.style;
255254
style.pointerEvents = 'none'; // needed for over items to get enter/leave
256-
// style.cursor = 'move'; // TODO: can't set with pointerEvents=none !
255+
// style.cursor = 'move'; // TODO: can't set with pointerEvents=none ! (done in CSS as well)
257256
style['min-width'] = 0; // since we no longer relative to our parent and we don't resize anyway (normally 100/#column %)
258257
style.width = this.dragOffset.width + 'px';
259258
style.height = this.dragOffset.height + 'px';
@@ -271,6 +270,7 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
271270

272271
/** @internal restore back the original style before dragging */
273272
protected _removeHelperStyle(): DDDraggable {
273+
this.helper.classList.remove('ui-draggable-dragging');
274274
let node = (this.helper as GridItemHTMLElement)?.gridstackNode;
275275
// don't bother restoring styles if we're gonna remove anyway...
276276
if (this.dragElementOriginStyle && (!node || !node._isAboutToRemove)) {

src/dd-droppable.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { DDBaseImplement, HTMLElementExtendOpt } from './dd-base-impl';
99
import { Utils } from './utils';
1010
import { DDElementHost } from './dd-element';
1111
import { isTouch, pointerenter, pointerleave } from './dd-touch';
12+
import { GridHTMLElement } from './gridstack';
1213

1314
export interface DDDroppableOpt {
1415
accept?: string | ((el: HTMLElement) => boolean);
@@ -86,34 +87,34 @@ export class DDDroppable extends DDBaseImplement implements HTMLElementExtendOpt
8687
/** @internal called when the cursor enters our area - prepare for a possible drop and track leaving */
8788
protected _mouseEnter(e: MouseEvent): void {
8889
// console.log(`${count++} Enter ${this.el.id || (this.el as GridHTMLElement).gridstack.opts.id}`); // TEST
89-
if (!DDManager.dragElement /* || DDManager.dropElement === this*/) return;
90+
if (!DDManager.dragElement) return;
9091
if (!this._canDrop()) return;
9192
e.preventDefault();
9293
e.stopPropagation();
9394

95+
// make sure when we enter this, that the last one gets a leave FIRST to correctly cleanup as we don't always do
96+
if (DDManager.dropElement && DDManager.dropElement !== this) {
97+
DDManager.dropElement._mouseLeave(e as DragEvent);
98+
}
99+
DDManager.dropElement = this;
100+
94101
const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'dropover' });
95102
if (this.option.over) {
96103
this.option.over(ev, this._ui(DDManager.dragElement))
97104
}
98105
this.triggerEvent('dropover', ev);
99106
this.el.classList.add('ui-droppable-over');
100-
101-
// make sure when we enter this, that the last one gets a leave to correctly cleanup as we don't always do
102-
if (DDManager.dropElement && DDManager.dropElement !== this) {
103-
DDManager.dropElement._mouseLeave(e as DragEvent);
104-
}
105-
DDManager.dropElement = this;
106107
// console.log('tracking'); // TEST
107108
}
108109

109110
/** @internal called when the item is leaving our area, stop tracking if we had moving item */
110-
protected _mouseLeave(event: DragEvent): void {
111+
protected _mouseLeave(e: MouseEvent): void {
111112
// console.log(`${count++} Leave ${this.el.id || (this.el as GridHTMLElement).gridstack.opts.id}`); // TEST
112113
if (!DDManager.dragElement || DDManager.dropElement !== this) return;
113-
event.preventDefault();
114-
event.stopPropagation();
114+
e.preventDefault();
115+
e.stopPropagation();
115116

116-
const ev = Utils.initEvent<DragEvent>(event, { target: this.el, type: 'dropout' });
117+
const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'dropout' });
117118
if (this.option.out) {
118119
this.option.out(ev, this._ui(DDManager.dragElement))
119120
}
@@ -131,7 +132,7 @@ export class DDDroppable extends DDBaseImplement implements HTMLElementExtendOpt
131132
parent = parent.parentElement;
132133
}
133134
if (parentDrop) {
134-
parentDrop._mouseEnter(event);
135+
parentDrop._mouseEnter(e);
135136
}
136137
}
137138
}

src/dd-resizable-handle.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,42 +72,48 @@ export class DDResizableHandle {
7272
}
7373

7474
/** @internal called on mouse down on us: capture move on the entire document (mouse might not stay on us) until we release the mouse */
75-
protected _mouseDown(e: MouseEvent): void {
76-
e.preventDefault();
75+
protected _mouseDown(e: MouseEvent) {
7776
this.mouseDownEvent = e;
7877
document.addEventListener('mousemove', this._mouseMove, true); // capture, not bubble
79-
document.addEventListener('mouseup', this._mouseUp);
78+
document.addEventListener('mouseup', this._mouseUp, true);
8079
if (isTouch) {
8180
this.el.addEventListener('touchmove', touchmove);
8281
this.el.addEventListener('touchend', touchend);
8382
}
83+
e.stopPropagation();
84+
e.preventDefault();
8485
}
8586

8687
/** @internal */
87-
protected _mouseMove(e: MouseEvent): void {
88+
protected _mouseMove(e: MouseEvent) {
8889
let s = this.mouseDownEvent;
89-
// don't start unless we've moved at least 3 pixels
90-
if (!this.moving && Math.abs(e.x - s.x) + Math.abs(e.y - s.y) > 2) {
90+
if (this.moving) {
91+
this._triggerEvent('move', e);
92+
} else if (Math.abs(e.x - s.x) + Math.abs(e.y - s.y) > 2) {
93+
// don't start unless we've moved at least 3 pixels
9194
this.moving = true;
9295
this._triggerEvent('start', this.mouseDownEvent);
93-
} else if (this.moving) {
9496
this._triggerEvent('move', e);
9597
}
98+
e.stopPropagation();
99+
e.preventDefault();
96100
}
97101

98102
/** @internal */
99-
protected _mouseUp(e: MouseEvent): void {
103+
protected _mouseUp(e: MouseEvent) {
100104
if (this.moving) {
101-
this._triggerEvent('resizestop', e);
105+
this._triggerEvent('stop', e);
102106
}
103107
document.removeEventListener('mousemove', this._mouseMove, true);
104-
document.removeEventListener('mouseup', this._mouseUp);
108+
document.removeEventListener('mouseup', this._mouseUp, true);
105109
if (isTouch) {
106110
this.el.removeEventListener('touchmove', touchmove);
107111
this.el.removeEventListener('touchend', touchend);
108112
}
109113
delete this.moving;
110114
delete this.mouseDownEvent;
115+
e.stopPropagation();
116+
e.preventDefault();
111117
}
112118

113119
/** @internal */

src/dd-resizable.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,11 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
5252
super();
5353
this.el = el;
5454
this.option = opts;
55+
// create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions)
56+
this._mouseOver = this._mouseOver.bind(this);
57+
this._mouseOut = this._mouseOut.bind(this);
5558
this.enable();
56-
this._setupAutoHide();
59+
this._setupAutoHide(this.option.autoHide);
5760
this._setupHandlers();
5861
}
5962

@@ -79,10 +82,7 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
7982

8083
public destroy(): void {
8184
this._removeHandlers();
82-
if (this.option.autoHide) {
83-
this.el.removeEventListener('mouseover', this._showHandlers);
84-
this.el.removeEventListener('mouseout', this._hideHandlers);
85-
}
85+
this._setupAutoHide(false);
8686
this.el.classList.remove('ui-resizable');
8787
delete this.el;
8888
super.destroy();
@@ -97,34 +97,36 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
9797
this._setupHandlers();
9898
}
9999
if (updateAutoHide) {
100-
this._setupAutoHide();
100+
this._setupAutoHide(this.option.autoHide);
101101
}
102102
return this;
103103
}
104104

105-
/** @internal */
106-
protected _setupAutoHide(): DDResizable {
107-
if (this.option.autoHide) {
105+
/** @internal turns auto hide on/off */
106+
protected _setupAutoHide(auto: boolean): DDResizable {
107+
if (auto) {
108108
this.el.classList.add('ui-resizable-autohide');
109109
// use mouseover/mouseout instead of mouseenter/mouseleave to get better performance;
110-
this.el.addEventListener('mouseover', this._showHandlers);
111-
this.el.addEventListener('mouseout', this._hideHandlers);
110+
this.el.addEventListener('mouseover', this._mouseOver);
111+
this.el.addEventListener('mouseout', this._mouseOut);
112112
} else {
113113
this.el.classList.remove('ui-resizable-autohide');
114-
this.el.removeEventListener('mouseover', this._showHandlers);
115-
this.el.removeEventListener('mouseout', this._hideHandlers);
114+
this.el.removeEventListener('mouseover', this._mouseOver);
115+
this.el.removeEventListener('mouseout', this._mouseOut);
116116
}
117117
return this;
118118
}
119119

120120
/** @internal */
121-
protected _showHandlers = () => {
121+
protected _mouseOver(e: Event) {
122122
this.el.classList.remove('ui-resizable-autohide');
123+
e.stopPropagation();
123124
}
124125

125126
/** @internal */
126-
protected _hideHandlers = () => {
127+
protected _mouseOut(e: Event) {
127128
this.el.classList.add('ui-resizable-autohide');
129+
e.stopPropagation();
128130
}
129131

130132
/** @internal */

src/gridstack.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ $animation_speed: .3s !default;
133133
}
134134
.ui-draggable-dragging {
135135
will-change: left, top;
136+
cursor: move;
136137
}
137138
.ui-resizable-resizing {
138139
will-change: width, height;

0 commit comments

Comments
 (0)