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.
+
+
+
+
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;