diff --git a/README.md b/README.md index 3149a3a4d..e1b40a8b4 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Join us on Slack: https://gridstackjs.troolee.com - [Requirements](#requirements) - [API Documentation](#api-documentation) - [Extend Library](#extend-library) + - [Extend Engine](#extend-engine) - [Change grid columns](#change-grid-columns) - [Custom columns CSS](#custom-columns-css) - [Override resizable/draggable options](#override-resizabledraggable-options) @@ -186,6 +187,27 @@ let grid = GridStack.init(); grid.printCount(); ``` +## Extend Engine + +You can now (5.1+) easily create your own layout engine to further customize you usage. Here is a typescript example + +```ts +import { GridStack, GridStackEngine, GridStackNod, GridStackMoveOpts } from 'gridstack'; + +class CustomEngine extends GridStackEngine { + + /** refined this to move the node to the given new location */ + public moveNode(node: GridStackNode, o: GridStackMoveOpts): boolean { + // keep the same original X and Width and let base do it all... + o.x = node.x; + o.w = node.w; + return super.moveNode(node, o); + } +} + +GridStack.registerEngine(CustomEngine); // globally set our custom class +``` + ## Change grid columns GridStack makes it very easy if you need [1-12] columns out of the box (default is 12), but you always need **2 things** if you need to customize this: diff --git a/demo/custom-engine.html b/demo/custom-engine.html new file mode 100644 index 000000000..8eda8e981 --- /dev/null +++ b/demo/custom-engine.html @@ -0,0 +1,75 @@ + + + + + + + Custom Engine + + + + + + +
+

Custom Engine

+

shows a custom engine subclass in Typescript that only allows objects to move vertically.

+
+ Add Widget + float: true +
+

+
+
+ + + + diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 86c0e7549..46f38a4e2 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -69,6 +69,7 @@ Change log ## 5.0.0-dev (TBD) +* add `GridStack.registerEngine()` to let user use their own custom layout engine subclass. Thank you [Thomas] for sponsoring it. ## 5.0.0 (2022-01-10) * add [#992](https://github.com/gridstack/gridstack.js/issues/992) support dragging into and out of nested grids from parents! Thank you [@arclogos132](https://github.com/arclogos132) for sponsoring it. diff --git a/doc/README.md b/doc/README.md index 995a0fb18..52d82d3a0 100644 --- a/doc/README.md +++ b/doc/README.md @@ -27,6 +27,7 @@ gridstack.js API - [`initAll(options: GridStackOptions = {}, selector = '.grid-stack'): GridStack[]`](#initalloptions-gridstackoptions---selector--grid-stack-gridstack) - [`addGrid(parent: HTMLElement, opt: GridStackOptions = {}): GridStack `](#addgridparent-htmlelement-opt-gridstackoptions---gridstack-) - [`setupDragIn(dragIn?: string, dragInOptions?: DDDragInOpt)`](#setupdragindragin-string-draginoptions-dddraginopt) + - [`GridStack.registerEngine(engineClass: typeof GridStackEngine)`](#gridstackregisterengineengineclass-typeof-gridstackengine) - [API](#api) - [`addWidget(el?: GridStackWidget | GridStackElement, options?: GridStackWidget)`](#addwidgetel-gridstackwidget--gridstackelement-options-gridstackwidget) - [`batchUpdate()`](#batchupdate) @@ -100,6 +101,7 @@ gridstack.js API * **Note2**: instead of 'clone' you can also pass your own function (get passed the event). - `draggable` - allows to override draggable options. (default: `{handle: '.grid-stack-item-content', scroll: false, appendTo: 'body', containment: null}`) - `dragOut` to let user drag nested grid items out of a parent or not (default false) See [example](http://gridstackjs.com/demo/nested.html) +- `engineClass` - the type of engine to create (so you can subclass) default to GridStackEngine - `float` - enable floating widgets (default: `false`) See [example](http://gridstackjs.com/demo/float.html) - `handle` - draggable handle selector (default: `'.grid-stack-item-content'`) - `handleClass` - draggable handle class (e.g. `'grid-stack-item-content'`). If set `handle` is ignored (default: `null`) @@ -321,6 +323,10 @@ Called during `GridStack.init()` as options, but can also be called directly (la * @param dragInOptions options - see `DDDragInOpt`. (default: `{revert: 'invalid', handle: '.grid-stack-item-content', scroll: false, appendTo: 'body'}` but you will probably also want `helper: 'clone'` or your own callback function). + +### `GridStack.registerEngine(engineClass: typeof GridStackEngine)` + +* call to specify global custom engine subclass - see instead `GridStackOptions.engineClass` if you only need to replace just one instance. ## API ### `addWidget(el?: GridStackWidget | GridStackElement, options?: GridStackWidget)` diff --git a/src/gridstack-engine.ts b/src/gridstack-engine.ts index fe6bddfeb..30cf730aa 100644 --- a/src/gridstack-engine.ts +++ b/src/gridstack-engine.ts @@ -622,14 +622,8 @@ export class GridStackEngine { if (Utils.samePos(node, o)) return false; let prevPos: GridStackPosition = Utils.copyPos({}, node); - // during while() collisions make sure to check entire row so larger items don't leap frog small ones (push them all down) - let area = nn; - // if (this._useEntireRowArea(node, nn)) { - // area = {x: 0, w: this.column, y: nn.y, h: nn.h}; - // } - // check if we will need to fix collision at our new location - let collides = this.collideAll(node, area, o.skip); + let collides = this.collideAll(node, nn, o.skip); let needToMove = true; if (collides.length) { // now check to make sure we actually collided over 50% surface area while dragging diff --git a/src/gridstack.ts b/src/gridstack.ts index 6cd1cebb7..807d1cc63 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -179,6 +179,14 @@ export class GridStack { return grid; } + /** call this method to register your engine instead of the default one. + * See instead `GridStackOptions.engineClass` if you only need to + * replace just one instance. + */ + static registerEngine(engineClass: typeof GridStackEngine) { + GridStack.engineClass = engineClass; + } + /** scoping so users can call GridStack.Utils.sort() for example */ public static Utils = Utils; @@ -194,6 +202,8 @@ export class GridStack { /** grid options - public for classes to access, but use methods to modify! */ public opts: GridStackOptions; + protected static engineClass: typeof GridStackEngine; + /** @internal create placeholder DIV as needed */ public get placeholder(): HTMLElement { if (!this._placeholder) { @@ -321,7 +331,8 @@ export class GridStack { this._setStaticClass(); - this.engine = new GridStackEngine({ + let engineClass = this.opts.engineClass || GridStack.engineClass || GridStackEngine; + this.engine = new engineClass({ column: this.getColumn(), float: this.opts.float, maxRow: this.opts.maxRow, diff --git a/src/types.ts b/src/types.ts index e320ddd4a..5d35560ed 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,6 +4,7 @@ */ import { GridStack } from './gridstack'; +import { GridStackEngine } from './gridstack-engine'; /** different layout options when changing # of columns, @@ -105,6 +106,9 @@ export interface GridStackOptions { /** let user drag nested grid items out of a parent or not (default false) */ dragOut?: boolean; + /** the type of engine to create (so you can subclass) default to GridStackEngine */ + engineClass?: typeof GridStackEngine; + /** enable floating widgets (default?: false) See example (http://gridstack.github.io/gridstack.js/demo/float.html) */ float?: boolean;