diff --git a/src/dd-resizable-handle.ts b/src/dd-resizable-handle.ts index d4137e4c4..dcb04277e 100644 --- a/src/dd-resizable-handle.ts +++ b/src/dd-resizable-handle.ts @@ -4,9 +4,9 @@ */ import { isTouch, pointerdown, touchend, touchmove, touchstart } from './dd-touch'; -import { GridItemHTMLElement } from './gridstack'; +import { DDResizableOpt, GridItemHTMLElement } from './gridstack'; -export interface DDResizableHandleOpt { +export interface DDResizableHandleOpt extends DDResizableOpt { start?: (event) => void; move?: (event) => void; stop?: (event) => void; @@ -34,18 +34,34 @@ export class DDResizableHandle { /** @internal */ protected _init(): DDResizableHandle { - const el = this.el = document.createElement('div'); - el.classList.add('ui-resizable-handle'); - el.classList.add(`${DDResizableHandle.prefix}${this.dir}`); - el.style.zIndex = '100'; - el.style.userSelect = 'none'; - this.host.appendChild(this.el); + if (this.option.element) { + try { + this.el = this.option.element instanceof HTMLElement + ? this.option.element + : this.host.querySelector(this.option.element) + } catch (error) { + this.option.element = undefined // make sure destroy handles it correctly + console.error("Query for resizeable handle failed, falling back", error) + } + } + + if (!this.el) { + this.el = document.createElement('div'); + this.host.appendChild(this.el); + } + + this.el.classList.add('ui-resizable-handle'); + this.el.classList.add(`${DDResizableHandle.prefix}${this.dir}`); + this.el.style.zIndex = '100'; + this.el.style.userSelect = 'none'; + this.el.addEventListener('mousedown', this._mouseDown); if (isTouch) { this.el.addEventListener('touchstart', touchstart); this.el.addEventListener('pointerdown', pointerdown); // this.el.style.touchAction = 'none'; // not needed unlike pointerdown doc comment } + return this; } @@ -57,7 +73,9 @@ export class DDResizableHandle { this.el.removeEventListener('touchstart', touchstart); this.el.removeEventListener('pointerdown', pointerdown); } - this.host.removeChild(this.el); + if (!this.option.element) { + this.host.removeChild(this.el); + } delete this.el; delete this.host; return this; diff --git a/src/dd-resizable.ts b/src/dd-resizable.ts index 2f1f3ca35..fe48071ab 100644 --- a/src/dd-resizable.ts +++ b/src/dd-resizable.ts @@ -15,6 +15,7 @@ import { DDManager } from './dd-manager'; export interface DDResizableOpt { autoHide?: boolean; handles?: string; + element?: string | HTMLElement; maxHeight?: number; maxHeightMoveUp?: number; maxWidth?: number; @@ -153,6 +154,7 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt this.handlers = this.option.handles.split(',') .map(dir => dir.trim()) .map(dir => new DDResizableHandle(this.el, dir, { + ...this.option, start: (event: MouseEvent) => { this._resizeStart(event); }, diff --git a/src/types.ts b/src/types.ts index cd48102bb..138e23328 100644 --- a/src/types.ts +++ b/src/types.ts @@ -464,6 +464,11 @@ export interface DDResizeOpt { * Note: it is not recommended to resize from the top sides as weird side effect may occur. */ handles?: string; + /** + * Custom element or query inside the widget node that is used instead of the + * generated resize handle. + */ + element?: string | HTMLElement } /** Drag&Drop remove options */