From 6c0b2368acdde7e3fb408621b3b06daa0a951286 Mon Sep 17 00:00:00 2001 From: Alain Dumesny Date: Fri, 14 Oct 2022 16:23:27 -0700 Subject: [PATCH] fix removeWidget() after it's gone from DOM * make sure removeWidget() handles when item has been first removed from DOM (like Angular/React/Vue would do). This bug had been there for 3 years, but shown it's ugly head in v6. --- demo/serialization.html | 18 ++++++++++++------ doc/CHANGES.md | 4 ++++ src/dd-touch.ts | 2 +- src/gridstack.ts | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/demo/serialization.html b/demo/serialization.html index adaadace0..656832372 100644 --- a/demo/serialization.html +++ b/demo/serialization.html @@ -44,39 +44,45 @@

Serialization demo

{x: 1, y: 3, id: '4'} ]; serializedData.forEach((n, i) => - n.content = `
${i}
${n.content ? n.content : ''}`); + n.content = `
${i}
${n.content ? n.content : ''}`); let serializedFull; // 2.x method - just saving list of widgets with content (default) - loadGrid = function() { + function loadGrid() { grid.load(serializedData, true); // update things } // 2.x method - saveGrid = function() { + function saveGrid() { delete serializedFull; serializedData = grid.save(); document.querySelector('#saved-data').value = JSON.stringify(serializedData, null, ' '); } // 3.1 full method saving the grid options + children (which is recursive for nested grids) - saveFullGrid = function() { + function saveFullGrid() { serializedFull = grid.save(true, true); serializedData = serializedFull.children; document.querySelector('#saved-data').value = JSON.stringify(serializedFull, null, ' '); } // 3.1 full method to reload from scratch - delete the grid and add it back from JSON - loadFullGrid = function() { + function loadFullGrid() { if (!serializedFull) return; grid.destroy(true); // nuke everything grid = GridStack.addGrid(document.querySelector('#gridCont'), serializedFull) } - clearGrid = function() { + function clearGrid() { grid.removeAll(); } + function removeWidget(el) { + // TEST removing from DOM first like Angular/React/Vue would do + el.remove(); + grid.removeWidget(el, false); + } + loadGrid(); diff --git a/doc/CHANGES.md b/doc/CHANGES.md index abb6ec1a5..2624dc421 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/)* +- [7.0.2 (TBD)](#702-tbd) - [7.0.1 (2022-10-14)](#701-2022-10-14) - [7.0.0 (2022-10-09)](#700-2022-10-09) - [6.0.3 (2022-10-08)](#603-2022-10-08) @@ -74,6 +75,9 @@ Change log +## 7.0.2 (TBD) +* fixed [#2081](https://github.com/gridstack/gridstack.js/issues/2081) removeWidget() after it's gone from DOM + ## 7.0.1 (2022-10-14) * fixed [#2073](https://github.com/gridstack/gridstack.js/issues/2073) SSR (server side rendering) isTouch issue (introduced in v6) * fixed - removing last item delete sub-grid that are not auto-generated (nested.html vs nested_advanced.html) diff --git a/src/dd-touch.ts b/src/dd-touch.ts index 3dfc09b28..c5ae15ca4 100644 --- a/src/dd-touch.ts +++ b/src/dd-touch.ts @@ -10,7 +10,7 @@ import { DDManager } from './dd-manager'; * should we use this instead ? (what we had for always showing resize handles) * /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) */ -export const isTouch: boolean = typeof window !== 'undefined' && typeof document !== 'undefined' && +export const isTouch: boolean = typeof window !== 'undefined' && typeof document !== 'undefined' && ( 'ontouchstart' in document || 'ontouchstart' in window // || !!window.TouchEvent // true on Windows 10 Chrome desktop so don't use this diff --git a/src/gridstack.ts b/src/gridstack.ts index 3bd07ef2e..7cd5a1cb0 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -1010,7 +1010,7 @@ export class GridStack { */ public removeWidget(els: GridStackElement, removeDOM = true, triggerEvent = true): GridStack { GridStack.getElements(els).forEach(el => { - if (el.parentElement !== this.el) return; // not our child! + if (el.parentElement && el.parentElement !== this.el) return; // not our child! let node = el.gridstackNode; // For Meteor support: https://github.com/gridstack/gridstack.js/pull/272 if (!node) {