From 5111f99ce6d88a602c37ec4e7e4e98164ca07007 Mon Sep 17 00:00:00 2001 From: Alain Dumesny Date: Sat, 17 Oct 2020 15:49:48 -0700 Subject: [PATCH] fix for static grid, enale dragging on fly * more complete fix for #858 * grid `static: true` to no longer add any drag&drop (even disabled) which should speed things up, and `setStatic(T/F)` will now correctly add it back/delete for items that need it only. * fixed JQ draggable warning if not initialized * add `GridStackWidget.html` now lets you add any HTML content when calling `grid.load()` * added demo showing static/non-static switch for debugging/info --- demo/index.html | 1 + demo/static.html | 43 +++++++++++++++++++++++++++ doc/CHANGES.md | 4 ++- doc/README.md | 1 + src/gridstack-dd.ts | 9 ++++++ src/gridstack.ts | 52 +++++++++++++++++++++------------ src/jq/gridstack-dd-jqueryui.ts | 12 ++++---- src/types.ts | 4 +++ 8 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 demo/static.html diff --git a/demo/index.html b/demo/index.html index f6de9e939..60e0ab898 100644 --- a/demo/index.html +++ b/demo/index.html @@ -17,6 +17,7 @@

Demos

  • Responsive
  • Right-To-Left (RTL)
  • Serialization
  • +
  • Static
  • Two grids
  • Vue2.js
  • Vue3.js
  • diff --git a/demo/static.html b/demo/static.html new file mode 100644 index 000000000..9058c43b3 --- /dev/null +++ b/demo/static.html @@ -0,0 +1,43 @@ + + + + + + + Static Grid + + + + + + +
    +

    Static vs can move/drag Demo

    +
    + Static + Editable +
    +

    +
    +
    + + + + diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 2a1af01c6..2fe8b39b5 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -41,7 +41,9 @@ Change log ## 2.0.2-dev -- TBD +- fix grid `static: true` to no longer add any drag&drop (even disabled) which should speed things up, and `setStatic(T/F)` will now correctly add it back/delete for items that need it only. +Also fixed JQ draggable warning if not initialized first [858](https://github.com/gridstack/gridstack.js/issues/858) +- add `GridStackWidget.html` now lets you add any HTML content when calling `grid.load()` ## 2.0.2 (2020-10-05) diff --git a/doc/README.md b/doc/README.md index 0ef0f49dd..916e3eb4b 100644 --- a/doc/README.md +++ b/doc/README.md @@ -137,6 +137,7 @@ You need to add `noResize` and `noMove` attributes to completely lock the widget - `noMove` - disable element moving - `resizeHandles` - sets resize handles for a specific widget. - `id`- (number | string) good for quick identification (for example in change event) +- `html` - (string) html content to be added when calling `grid.load()` as content inside the item ## Item attributes diff --git a/src/gridstack-dd.ts b/src/gridstack-dd.ts index f5ca92b82..bdfeef6d4 100644 --- a/src/gridstack-dd.ts +++ b/src/gridstack-dd.ts @@ -46,6 +46,15 @@ export class GridStackDD { this.grid = grid; } + /** removes any drag&drop present (called during destroy) */ + public remove(el: GridItemHTMLElement): GridStackDD { + this.draggable(el, 'destroy').resizable(el, 'destroy'); + if (el.gridstackNode) { + delete el.gridstackNode._initDD; // reset our DD init flag + } + return this; + } + public resizable(el: GridItemHTMLElement, opts: DDOpts, key?: DDKey, value?: DDValue): GridStackDD { return this; } diff --git a/src/gridstack.ts b/src/gridstack.ts index 46b7b8224..12a72473c 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -396,7 +396,7 @@ export class GridStack { if (typeof(addAndRemove) === 'function') { addAndRemove(w, true); } else { - this.addWidget('
    ', w); + this.addWidget(`
    ${w.html || ''}
    `, w); } } }); @@ -539,7 +539,7 @@ export class GridStack { */ public destroy(removeDOM = true): GridStack { this._updateWindowResizeEvent(true); - this.disable(); + this.setStatic(true); // permanently removes DD if (!removeDOM) { this.removeAll(removeDOM); this.el.classList.remove(this.opts._class); @@ -586,6 +586,7 @@ export class GridStack { * doEnable`s value by changing the disableDrag grid option (default: true). */ public enableMove(doEnable: boolean, includeNewWidgets = true): GridStack { + if (doEnable && this.opts.staticGrid) { return this; } // can't move a static grid! this.getGridItems().forEach(el => this.movable(el, doEnable)); if (includeNewWidgets) { this.opts.disableDrag = !doEnable; @@ -600,6 +601,7 @@ export class GridStack { * doEnable`s value by changing the disableResize grid option (default: true). */ public enableResize(doEnable: boolean, includeNewWidgets = true): GridStack { + if (doEnable && this.opts.staticGrid) { return this; } // can't size a static grid! this.getGridItems().forEach(el => this.resizable(el, doEnable)); if (includeNewWidgets) { this.opts.disableResize = !doEnable; @@ -756,6 +758,7 @@ export class GridStack { * @param val if true widget will be draggable. */ public movable(els: GridStackElement, val: boolean): GridStack { + if (val && this.opts.staticGrid) { return this; } // can't move a static grid! GridStack.getElements(els).forEach(el => { let node = el.gridstackNode; if (!node) { return } @@ -764,6 +767,7 @@ export class GridStack { this.dd.draggable(el, 'disable'); el.classList.remove('ui-draggable-handle'); } else { + this._prepareDragDropByNode(node); // init DD if need be this.dd.draggable(el, 'enable'); el.classList.remove('ui-draggable-handle'); } @@ -872,7 +876,7 @@ export class GridStack { // remove our DOM data (circular link) and drag&drop permanently delete el.gridstackNode; - this.dd.draggable(el, 'destroy').resizable(el, 'destroy'); + this.dd.remove(el); this.engine.removeNode(node, removeDOM, triggerEvent); @@ -895,7 +899,7 @@ export class GridStack { // always remove our DOM data (circular link) before list gets emptied and drag&drop permanently this.engine.nodes.forEach(n => { delete n.el.gridstackNode; - this.dd.draggable(n.el, 'destroy').resizable(n.el, 'destroy'); + this.dd.remove(n.el); }); this.engine.removeAll(removeDOM); this._triggerRemoveEvent(); @@ -924,6 +928,7 @@ export class GridStack { * @param val if true widget will be resizable. */ public resizable(els: GridStackElement, val: boolean): GridStack { + if (val && this.opts.staticGrid) { return this; } // can't resize a static grid! GridStack.getElements(els).forEach(el => { let node = el.gridstackNode; if (!node) { return; } @@ -931,6 +936,7 @@ export class GridStack { if (node.noResize) { this.dd.resizable(el, 'disable'); } else { + this._prepareDragDropByNode(node); // init DD if need be this.dd.resizable(el, 'enable'); } }); @@ -951,13 +957,19 @@ export class GridStack { } /** - * Toggle the grid static state. Also toggle the grid-stack-static class. - * @param staticValue if true the grid become static. + * Toggle the grid static state, which permanently removes/add Drag&Drop support, unlike disable()/enable() that just turns it off/on. + * Also toggle the grid-stack-static class. + * @param val if true the grid become static. */ - public setStatic(staticValue: boolean): GridStack { - this.opts.staticGrid = (staticValue === true); - this.enableMove(!staticValue); - this.enableResize(!staticValue); + public setStatic(val: boolean): GridStack { + if (this.opts.staticGrid === val) { return this; } + this.opts.staticGrid = val; + // either delete Drag&drop or initialize it + if (val) { + this.getGridItems().forEach(el => this.dd.remove(el)); + } else { + this.engine.nodes.forEach(n => this._prepareDragDropByNode(n)); + } this._setStaticClass(); return this; } @@ -1191,6 +1203,12 @@ export class GridStack { /** @internal prepares the element for drag&drop **/ private _prepareDragDropByNode(node: GridStackNode): GridStack { + // check if init already done or not needed (static/disabled) + if (node._initDD || this.opts.staticGrid || + ((node.noMove || this.opts.disableDrag) && (node.noResize || this.opts.disableResize))) { + return; + } + // variables used/cashed between the 3 start/move/end methods, in addition to node passed above let cellWidth: number; let cellHeight: number; @@ -1304,7 +1322,7 @@ export class GridStack { gridToNotify._gsEventHandler[event.type](event, target); } gridToNotify.engine.removedNodes.push(node); - gridToNotify.dd.draggable(el, 'destroy').resizable(el, 'destroy'); + gridToNotify.dd.remove(el); delete el.gridstackNode; // hint we're removing it next and break circular link gridToNotify._triggerRemoveEvent(); if (el.parentElement) { @@ -1350,16 +1368,14 @@ export class GridStack { stop: onEndMoving, resize: dragOrResize }); + node._initDD = true; // we've set DD support now if (node.noMove || this.opts.disableDrag || this.opts.staticGrid) { this.dd.draggable(el, 'disable'); } - if (node.noResize || this.opts.disableResize || this.opts.staticGrid) { this.dd.resizable(el, 'disable'); } - - this._writeAttr(el, node); return this; } @@ -1379,7 +1395,7 @@ export class GridStack { let node = this._readAttr(el, { el: el, grid: this }); node = this.engine.addNode(node, triggerAddEvent); el.gridstackNode = node; - + this._writeAttr(el, node); this._prepareDragDropByNode(node); return this; } @@ -1474,7 +1490,7 @@ export class GridStack { private _setStaticClass(): GridStack { let staticClassName = 'grid-stack-static'; - if (this.opts.staticGrid === true) { + if (this.opts.staticGrid) { this.el.classList.add(staticClassName); } else { this.el.classList.remove(staticClassName); @@ -1683,9 +1699,7 @@ export class GridStack { el = el.cloneNode(true) as GridItemHTMLElement; } else { el.remove(); // reduce flicker as we change depth here, and size further down - this.dd - .draggable(el, 'destroy') - .resizable(el, 'destroy'); + this.dd.remove(el); } el.gridstackNode = node; node.el = el; diff --git a/src/jq/gridstack-dd-jqueryui.ts b/src/jq/gridstack-dd-jqueryui.ts index 18aaf886c..7f8b98058 100644 --- a/src/jq/gridstack-dd-jqueryui.ts +++ b/src/jq/gridstack-dd-jqueryui.ts @@ -26,9 +26,9 @@ export class GridStackDDJQueryUI extends GridStackDD { public resizable(el: GridItemHTMLElement, opts: DDOpts, key?: DDKey, value?: DDValue): GridStackDD { let $el: JQuery = $(el); - if (opts === 'disable' || opts === 'enable') { - $el.resizable(opts); - } else if (opts === 'destroy') { + if (opts === 'enable') { + $el.resizable().resizable(opts); + } else if (opts === 'disable' || opts === 'destroy') { if ($el.data('ui-resizable')) { // error to call destroy if not there $el.resizable(opts); } @@ -47,9 +47,9 @@ export class GridStackDDJQueryUI extends GridStackDD { public draggable(el: GridItemHTMLElement, opts: DDOpts, key?: DDKey, value?: DDValue): GridStackDD { let $el: JQuery = $(el); - if (opts === 'disable' || opts === 'enable') { - $el.draggable(opts); - } else if (opts === 'destroy') { + if (opts === 'enable') { + $el.draggable().draggable('enable'); + } else if (opts === 'disable' || opts === 'destroy') { if ($el.data('ui-draggable')) { // error to call destroy if not there $el.draggable(opts); } diff --git a/src/types.ts b/src/types.ts index e0077026e..841faa37d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -204,6 +204,8 @@ export interface GridStackWidget { resizeHandles?: string; /** value for `data-gs-id` stored on the widget (default?: undefined) */ id?: numberOrString; + /** html to append inside the content */ + html?: string; } /** Drag&Drop resize options */ @@ -291,4 +293,6 @@ export interface GridStackNode extends GridStackWidget { _prevYPix?: number; /** @internal */ _temporaryRemoved?: boolean; + /** @internal */ + _initDD?: boolean; }