From 612f621e9d3d04eec7e35e586a012af867263911 Mon Sep 17 00:00:00 2001 From: Alain Dumesny Date: Sat, 29 Apr 2023 16:08:20 -0700 Subject: [PATCH] setupDragIn() shadow DOM support * fix #2275 * `setupDragIn()` now can take an array or elements (in addition to selector string) and optional parent root (for shadow DOM support) --- doc/CHANGES.md | 4 ++++ src/dd-draggable.ts | 2 +- src/gridstack.ts | 16 ++++++++-------- src/utils.ts | 34 +++++++++++++++++----------------- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/doc/CHANGES.md b/doc/CHANGES.md index c0bf8a8ca..8049a7155 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -5,6 +5,7 @@ Change log **Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* +- [8.0.0-dev (TBD)](#800-dev-tbd) - [8.0.0 (2023-04-29)](#800-2023-04-29) - [7.3.0 (2023-04-01)](#730-2023-04-01) - [7.2.3 (2023-02-02)](#723-2023-02-02) @@ -83,6 +84,9 @@ Change log +## 8.0.0-dev (TBD) +* feat: [#2275](https://github.com/gridstack/gridstack.js/issues/2275) `setupDragIn()` now can take an array or elements (in addition to selector string) and optional parent root (for shadow DOM support) + ## 8.0.0 (2023-04-29) * package is now ES2020 (TS exported files), webpack all.js still umd (better than commonjs for browsers), still have es5/ files unchanged (for now) * optimize [#2243](https://github.com/gridstack/gridstack.js/issues/2243) removed `gs-min|max_w|h` attribute generated in CSS or written out as they are never used for rendering, only for initial load. This reduce our column/row CSS in half! diff --git a/src/dd-draggable.ts b/src/dd-draggable.ts index 6aea74877..e9f384a23 100644 --- a/src/dd-draggable.ts +++ b/src/dd-draggable.ts @@ -266,7 +266,7 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt helper = Utils.cloneNode(this.el); } if (!document.body.contains(helper)) { - Utils.appendTo(helper, this.option.appendTo === 'parent' ? this.el.parentNode : this.option.appendTo); + Utils.appendTo(helper, this.option.appendTo === 'parent' ? this.el.parentElement : this.option.appendTo); } if (helper === this.el) { this.dragElementOriginStyle = DDDraggable.originStyleProp.map(prop => this.el.style[prop]); diff --git a/src/gridstack.ts b/src/gridstack.ts index b7c7b3edc..6df6c4b13 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -1666,20 +1666,20 @@ export class GridStack { * call to setup dragging in from the outside (say toolbar), by specifying the class selection and options. * Called during GridStack.init() as options, but can also be called directly (last param are used) in case the toolbar * is dynamically create and needs to be set later. - * @param dragIn string selector (ex: '.sidebar .grid-stack-item') + * @param dragIn string selector (ex: '.sidebar .grid-stack-item') or list of dom elements * @param dragInOptions options - see DDDragInOpt. (default: {handle: '.grid-stack-item-content', appendTo: 'body'} + * @param root optional root which defaults to document (for shadow dom) **/ - public static setupDragIn(dragIn?: string, dragInOptions?: DDDragInOpt): void { + public static setupDragIn(dragIn?: string | HTMLElement[], dragInOptions?: DDDragInOpt, root = document): void { if (dragInOptions?.pause !== undefined) { DDManager.pauseDrag = dragInOptions.pause; } - if (typeof dragIn === 'string') { - dragInOptions = {...dragInDefaultOptions, ...(dragInOptions || {})}; - Utils.getElements(dragIn).forEach(el => { - if (!dd.isDraggable(el)) dd.dragIn(el, dragInOptions); - }); - } + dragInOptions = {...dragInDefaultOptions, ...(dragInOptions || {})}; + let els: HTMLElement[] = (typeof dragIn === 'string') ? Utils.getElements(dragIn, root) : dragIn; + if (els.length) els?.forEach(el => { + if (!dd.isDraggable(el)) dd.dragIn(el, dragInOptions); + }); } /** diff --git a/src/utils.ts b/src/utils.ts index 3b53df71e..0d760b457 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -53,39 +53,39 @@ export function obsoleteAttr(el: HTMLElement, oldName: string, newName: string, */ export class Utils { - /** convert a potential selector into actual list of html elements */ - static getElements(els: GridStackElement): HTMLElement[] { + /** convert a potential selector into actual list of html elements. optional root which defaults to document (for shadow dom) */ + static getElements(els: GridStackElement, root = document): HTMLElement[] { if (typeof els === 'string') { - let list = document.querySelectorAll(els); + let list = root.querySelectorAll(els); if (!list.length && els[0] !== '.' && els[0] !== '#') { - list = document.querySelectorAll('.' + els); - if (!list.length) { list = document.querySelectorAll('#' + els) } + list = root.querySelectorAll('.' + els); + if (!list.length) { list = root.querySelectorAll('#' + els) } } return Array.from(list) as HTMLElement[]; } return [els]; } - /** convert a potential selector into actual single element */ - static getElement(els: GridStackElement): HTMLElement { + /** convert a potential selector into actual single element. optional root which defaults to document (for shadow dom) */ + static getElement(els: GridStackElement, root = document): HTMLElement { if (typeof els === 'string') { if (!els.length) return null; if (els[0] === '#') { - return document.getElementById(els.substring(1)); + return root.getElementById(els.substring(1)); } if (els[0] === '.' || els[0] === '[') { - return document.querySelector(els); + return root.querySelector(els); } // if we start with a digit, assume it's an id (error calling querySelector('#1')) as class are not valid CSS if(!isNaN(+els[0])) { // start with digit - return document.getElementById(els); + return root.getElementById(els); } - // finally try string, then id then class - let el = document.querySelector(els); - if (!el) { el = document.getElementById(els) } - if (!el) { el = document.querySelector('.' + els) } + // finally try string, then id, then class + let el = root.querySelector(els); + if (!el) { el = root.getElementById(els) } + if (!el) { el = root.querySelector('.' + els) } return el as HTMLElement; } return els; @@ -452,12 +452,12 @@ export class Utils { return node; } - public static appendTo(el: HTMLElement, parent: string | HTMLElement | Node): void { + public static appendTo(el: HTMLElement, parent: string | HTMLElement): void { let parentNode: HTMLElement; if (typeof parent === 'string') { - parentNode = document.querySelector(parent as string); + parentNode = Utils.getElement(parent); } else { - parentNode = parent as HTMLElement; + parentNode = parent; } if (parentNode) { parentNode.appendChild(el);