Skip to content

Commit cf5c0c7

Browse files
authored
Allow custom element resize handler (#3142)
* Allow nested resize handler * Fixed error when element is not a child of this node * Use an resize option instead for better compatibility * Use CRLF line endings * Make sure element is always created and warn the user
1 parent ec15d79 commit cf5c0c7

File tree

3 files changed

+34
-9
lines changed

3 files changed

+34
-9
lines changed

src/dd-resizable-handle.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
*/
55

66
import { isTouch, pointerdown, touchend, touchmove, touchstart } from './dd-touch';
7-
import { GridItemHTMLElement } from './gridstack';
7+
import { DDResizableOpt, GridItemHTMLElement } from './gridstack';
88

9-
export interface DDResizableHandleOpt {
9+
export interface DDResizableHandleOpt extends DDResizableOpt {
1010
start?: (event) => void;
1111
move?: (event) => void;
1212
stop?: (event) => void;
@@ -34,18 +34,34 @@ export class DDResizableHandle {
3434

3535
/** @internal */
3636
protected _init(): DDResizableHandle {
37-
const el = this.el = document.createElement('div');
38-
el.classList.add('ui-resizable-handle');
39-
el.classList.add(`${DDResizableHandle.prefix}${this.dir}`);
40-
el.style.zIndex = '100';
41-
el.style.userSelect = 'none';
42-
this.host.appendChild(this.el);
37+
if (this.option.element) {
38+
try {
39+
this.el = this.option.element instanceof HTMLElement
40+
? this.option.element
41+
: this.host.querySelector(this.option.element)
42+
} catch (error) {
43+
this.option.element = undefined // make sure destroy handles it correctly
44+
console.error("Query for resizeable handle failed, falling back", error)
45+
}
46+
}
47+
48+
if (!this.el) {
49+
this.el = document.createElement('div');
50+
this.host.appendChild(this.el);
51+
}
52+
53+
this.el.classList.add('ui-resizable-handle');
54+
this.el.classList.add(`${DDResizableHandle.prefix}${this.dir}`);
55+
this.el.style.zIndex = '100';
56+
this.el.style.userSelect = 'none';
57+
4358
this.el.addEventListener('mousedown', this._mouseDown);
4459
if (isTouch) {
4560
this.el.addEventListener('touchstart', touchstart);
4661
this.el.addEventListener('pointerdown', pointerdown);
4762
// this.el.style.touchAction = 'none'; // not needed unlike pointerdown doc comment
4863
}
64+
4965
return this;
5066
}
5167

@@ -57,7 +73,9 @@ export class DDResizableHandle {
5773
this.el.removeEventListener('touchstart', touchstart);
5874
this.el.removeEventListener('pointerdown', pointerdown);
5975
}
60-
this.host.removeChild(this.el);
76+
if (!this.option.element) {
77+
this.host.removeChild(this.el);
78+
}
6179
delete this.el;
6280
delete this.host;
6381
return this;

src/dd-resizable.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { DDManager } from './dd-manager';
1515
export interface DDResizableOpt {
1616
autoHide?: boolean;
1717
handles?: string;
18+
element?: string | HTMLElement;
1819
maxHeight?: number;
1920
maxHeightMoveUp?: number;
2021
maxWidth?: number;
@@ -153,6 +154,7 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
153154
this.handlers = this.option.handles.split(',')
154155
.map(dir => dir.trim())
155156
.map(dir => new DDResizableHandle(this.el, dir, {
157+
...this.option,
156158
start: (event: MouseEvent) => {
157159
this._resizeStart(event);
158160
},

src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,11 @@ export interface DDResizeOpt {
464464
* Note: it is not recommended to resize from the top sides as weird side effect may occur.
465465
*/
466466
handles?: string;
467+
/**
468+
* Custom element or query inside the widget node that is used instead of the
469+
* generated resize handle.
470+
*/
471+
element?: string | HTMLElement
467472
}
468473

469474
/** Drag&Drop remove options */

0 commit comments

Comments
 (0)