diff --git a/README.md b/README.md
index b9b9101e2..24633d688 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ Join us on Slack: https://gridstackjs.troolee.com
- [Touch devices support](#touch-devices-support)
- [Migrating to v0.6.x](#migrating-to-v06x)
- [Migrating to v1.0.0](#migrating-to-v100)
+ - [Migrating to v2.0.0](#migrating-to-v200)
- [Changes](#changes)
- [The Team](#the-team)
@@ -323,6 +324,20 @@ Recommend looking at the [many samples](./demo) for more code examples.
We're working on implementing HTML5 drag'n'drop through the plugin system. Right now it is still jquery-ui based. Because of that we are still bundling `jquery` (3.4.1) + `jquery-ui` (1.12.1 minimal drag|drop|resize) internally in `gridstack.all.js`. IFF your app needs to bring it's own version instead, you should **instead** include `gridstack-poly.min.js` (optional IE support) + `gridstack.min.js` + `gridstack.jQueryUI.min.js` + after you import your libs.
+## Migrating to v2.0.0
+
+make sure to read v1.0.0 migration first!
+
+v2.x is a Typescript rewrite of 1.x, using classes and overall code cleanup. You code might not need change from 1.x
+
+In general methods that used optional args as getting vs setting are not used in Typescript.
+Also legacy methods that used to take tons of parameters will now take an object.
+
+```
+removed `addWidget(el, x, y, width, ...)` --> use the widget options version instead `addWidget(el, {x, y, with,...})`
+`float()` to get value --> `getFloat()`
+```
+
Changes
=====
diff --git a/demo/anijs.html b/demo/anijs.html
index a4def831d..6acecfbe4 100644
--- a/demo/anijs.html
+++ b/demo/anijs.html
@@ -38,7 +38,7 @@
Widget added
});
function addWidget() {
- grid.addWidget('', 0, 0, Math.floor(1 + 3 * Math.random()), Math.floor(1 + 3 * Math.random()), true);
+ grid.addWidget('', {width: Math.floor(1 + 3 * Math.random()), height: Math.floor(1 + 3 * Math.random())});
};
var animationHelper = AniJS.getHelper();
diff --git a/demo/float.html b/demo/float.html
index d1509e3af..edf7c094e 100644
--- a/demo/float.html
+++ b/demo/float.html
@@ -50,8 +50,8 @@ Float grid demo
};
toggleFloat = function() {
- grid.float(! grid.float());
- document.querySelector('#float').innerHTML = 'float: ' + grid.float();
+ grid.float(! grid.getFloat());
+ document.querySelector('#float').innerHTML = 'float: ' + grid.getFloat();
};
addNewWidget();
diff --git a/demo/two.html b/demo/two.html
index 8c58335ff..9967f10d9 100644
--- a/demo/two.html
+++ b/demo/two.html
@@ -135,8 +135,8 @@ Two grids demo
});
function toggleFloat(button, i) {
- grids[i].float(! grids[i].float());
- button.innerHTML = 'float: ' + grids[i].float();
+ grids[i].float(! grids[i].getFloat());
+ button.innerHTML = 'float: ' + grids[i].getFloat();
}
function compact(i) {
diff --git a/doc/CHANGES.md b/doc/CHANGES.md
index 698778586..bacab24d5 100644
--- a/doc/CHANGES.md
+++ b/doc/CHANGES.md
@@ -37,6 +37,7 @@ Change log
- fix [1187](https://github.com/gridstack/gridstack.js/issues/1187) IE support for `CustomEvent` polyfill - thanks [@phil-blais](https://github.com/phil-blais)
- fix [1204](https://github.com/gridstack/gridstack.js/issues/1204) destroy drag&drop when removing node(s) instead of just disabling it.
- include SASS source files to npm package again [1193](https://github.com/gridstack/gridstack.js/pull/1193) - include SASS source files to npm package again [1193](https://github.com/gridstack/gridstack.js/pull/1193)
+- fix [1217](https://github.com/gridstack/gridstack.js/issues/1217) If I set `cellHeight` to some `vh`, only first grid will take `vh`, rest will use `px`
- add `getGridItems()` to return list of HTML grid items
## 1.1.0 (2020-02-29)
diff --git a/doc/README.md b/doc/README.md
index 3d78dbe30..dddaa1b60 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -22,7 +22,6 @@ gridstack.js API
- [gsresizestop(event, ui)](#gsresizestopevent-ui)
- [API](#api)
- [addWidget(el, [options])](#addwidgetel-options)
- - [addWidget(el, [x, y, width, height, autoPosition, minWidth, maxWidth, minHeight, maxHeight, id])](#addwidgetel-x-y-width-height-autoposition-minwidth-maxwidth-minheight-maxheight-id)
- [batchUpdate()](#batchupdate)
- [compact()](#compact)
- [cellHeight()](#cellheight)
@@ -239,30 +238,19 @@ grid.on('gsresizestop', function(event, element) {
### addWidget(el, [options])
-Creates new widget and returns it. Options is an object containing the fields x,y,width,height,etc... described below.
-
-### addWidget(el, [x, y, width, height, autoPosition, minWidth, maxWidth, minHeight, maxHeight, id])
-
-Creates new widget and returns it.
+Creates new widget and returns it. Options is an object containing the fields x,y,width,height,etc...
Parameters:
-- `el` - widget to add
-- `x`, `y`, `width`, `height` - widget position/dimensions (optional)
-- `autoPosition` - if `true` then `x`, `y` parameters will be ignored and widget will be places on the first available
-position (optional)
-- `minWidth` minimum width allowed during resize/creation (optional)
-- `maxWidth` maximum width allowed during resize/creation (optional)
-- `minHeight` minimum height allowed during resize/creation (optional)
-- `maxHeight` maximum height allowed during resize/creation (optional)
-- `id` value for `data-gs-id` (optional)
+- `el` - html element or string definition to add
+- `options` widget position/size options (optional) - see GridStackWidget
Widget will be always placed even if result height is more than actual grid height. You need to use `willItFit` method
before calling `addWidget` for additional check.
```js
var grid = GridStack.init();
-grid.addWidget(el, 0, 0, 3, 2, true);
+grid.addWidget('', {width: 3});
```
### batchUpdate()
@@ -507,15 +495,14 @@ Returns `true` if the `height` of the grid will be less the vertical constraint.
have `height` constraint.
```js
-if (grid.willItFit(newNode.x, newNode.y, newNode.width, newNode.height, true)) {
- grid.addWidget(newNode.el, newNode.x, newNode.y, newNode.width, newNode.height, true);
+if (grid.willItFit(newNode.x, newNode.y, newNode.width, newNode.height, newNode.autoPosition)) {
+ grid.addWidget(newNode.el, newNode);
}
else {
alert('Not enough free space to place the widget');
}
```
-
## Utils
### GridStack.Utils.sort(nodes[, dir[, width]])
diff --git a/spec/gridstack-spec.js b/spec/gridstack-spec.js
index ffd7e5169..2473600d4 100644
--- a/spec/gridstack-spec.js
+++ b/spec/gridstack-spec.js
@@ -753,7 +753,8 @@ describe('gridstack', function() {
});
it('should keep all widget options the same (autoPosition off', function() {
var grid = GridStack.init({float: true});;
- var widget = grid.addWidget(widgetHTML, 6, 7, 2, 3, false, 1, 4, 2, 5, 'coolWidget');
+ var widget = grid.addWidget(widgetHTML, {x: 6, y:7, width:2, height:3, autoPosition:false,
+ mindWidth:1, maxWidth:4, mindHeight:2, maxHeight:5, id:'coolWidget'});
var $widget = $(widget);
expect(parseInt($widget.attr('data-gs-x'), 10)).toBe(6);
expect(parseInt($widget.attr('data-gs-y'), 10)).toBe(7);
@@ -767,9 +768,9 @@ describe('gridstack', function() {
expect($widget.attr('data-gs-id')).toBe('coolWidget');
// should move widget to top with float=false
- expect(grid.float()).toBe(true);
+ expect(grid.getFloat()).toBe(true);
grid.float(false);
- expect(grid.float()).toBe(false);
+ expect(grid.getFloat()).toBe(false);
expect(parseInt($widget.attr('data-gs-x'), 10)).toBe(6);
expect(parseInt($widget.attr('data-gs-y'), 10)).toBe(4); // <--- from 7 to 4 below second original widget
expect(parseInt($widget.attr('data-gs-width'), 10)).toBe(2);
@@ -783,7 +784,7 @@ describe('gridstack', function() {
// should not move again (no-op)
grid.float(true);
- expect(grid.float()).toBe(true);
+ expect(grid.getFloat()).toBe(true);
expect(parseInt($widget.attr('data-gs-x'), 10)).toBe(6);
expect(parseInt($widget.attr('data-gs-y'), 10)).toBe(4);
expect(parseInt($widget.attr('data-gs-width'), 10)).toBe(2);
@@ -806,7 +807,7 @@ describe('gridstack', function() {
});
it('should change x, y coordinates for widgets.', function() {
var grid = GridStack.init({float: true});
- var widget = grid.addWidget(widgetHTML, 9, 7, 2, 3, true);
+ var widget = grid.addWidget(widgetHTML, {x:9, y:7, width:2, height:3, autoPosition:true});
var $widget = $(widget);
expect(parseInt($widget.attr('data-gs-x'), 10)).not.toBe(9);
expect(parseInt($widget.attr('data-gs-y'), 10)).not.toBe(7);
@@ -925,14 +926,14 @@ describe('gridstack', function() {
it('should clear x position', function() {
var grid = GridStack.init({float: true});
var widgetHTML = '';
- var widget = grid.addWidget(widgetHTML, null, null, undefined);
+ var widget = grid.addWidget(widgetHTML, {x:null, y:null, width:undefined});
var $widget = $(widget);
expect(parseInt($widget.attr('data-gs-x'), 10)).toBe(8);
expect(parseInt($widget.attr('data-gs-y'), 10)).toBe(0);
});
});
- describe('method float()', function() {
+ describe('method getFloat()', function() {
beforeEach(function() {
document.body.insertAdjacentHTML('afterbegin', gridstackHTML);
});
@@ -941,15 +942,15 @@ describe('gridstack', function() {
});
it('should match true/false only', function() {
var grid = GridStack.init({float: true});
- expect(grid.float()).toBe(true);
+ expect(grid.getFloat()).toBe(true);
grid.float(0);
- expect(grid.float()).toBe(false);
+ expect(grid.getFloat()).toBe(false);
grid.float(null);
- expect(grid.float()).toBe(false);
+ expect(grid.getFloat()).toBe(false);
grid.float(undefined);
- expect(grid.float()).toBe(false);
+ expect(grid.getFloat()).toBe(false);
grid.float(false);
- expect(grid.float()).toBe(false);
+ expect(grid.getFloat()).toBe(false);
});
});
diff --git a/spec/gridstack-tests.ts b/spec/gridstack-tests.ts
deleted file mode 100644
index 94a7e00bb..000000000
--- a/spec/gridstack-tests.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { GridStack, GridstackOptions, MousePosition } from '../src/gridstack';
-
-var options: GridstackOptions = {
- float: true
-};
-
-var grid: GridStack = GridStack.init(options);
-var gsFromElement: GridStack = GridStack.get();
-var gsFromElement2: GridStack = ($('.grid-stack').get(0) as any).gridstack;
-
-if (gsFromElement !== grid) throw Error('These should match!');
-if (gsFromElement2 !== grid) throw Error('These should match!');
-
-var gridItem = ''
-
-grid.addWidget(gridItem, {width: 2});
-grid.addWidget(gridItem, 1, 2, 3, 4, true);
-grid.makeWidget(document.createElement('div'));
-grid.batchUpdate();
-grid.cellHeight();;
-grid.cellHeight(2);
-grid.cellWidth();
-grid.getCellFromPixel({ left:20, top: 20 });
-grid.removeAll(false);
diff --git a/src/gridstack-engine.ts b/src/gridstack-engine.ts
index 294e77932..f6a6cf6ae 100644
--- a/src/gridstack-engine.ts
+++ b/src/gridstack-engine.ts
@@ -71,8 +71,16 @@ export class GridStackEngine {
while (true) {
let collisionNode = this.nodes.find( n => n !== node && Utils.isIntercepted(n, nn), {node: node, nn: nn});
if (!collisionNode) { return; }
- this.moveNode(collisionNode, collisionNode.x, node.y + node.height,
- collisionNode.width, collisionNode.height, true);
+ let moved;
+ if (collisionNode.locked) {
+ // if colliding with a locked item, move ourself instead
+ moved = this.moveNode(node, node.x, collisionNode.y + collisionNode.height,
+ node.width, node.height, true);
+ } else {
+ moved = this.moveNode(collisionNode, collisionNode.x, node.y + node.height,
+ collisionNode.width, collisionNode.height, true);
+ }
+ if (!moved) { return; } // break inf loop if we couldn't move after all (ex: maxRow, fixed)
}
}
@@ -112,7 +120,7 @@ export class GridStackEngine {
}
/** float getter method */
- public get float(): boolean { return this._float; }
+ public get float(): boolean { return this._float || false; }
private _sortNodes(dir?: -1 | 1) {
this.nodes = Utils.sort(this.nodes, dir, this.column);
@@ -180,13 +188,6 @@ export class GridStackEngine {
let defaults = {width: 1, height: 1, x: 0, y: 0};
node = Utils.defaults(node, defaults);
- // convert any strings over
- /* TODO: check
- node.x = parseInt(node.x);
- node.y = parseInt(node.y);
- node.width = parseInt(node.width);
- node.height = parseInt(node.height);
- */
node.autoPosition = node.autoPosition || false;
node.noResize = node.noResize || false;
node.noMove = node.noMove || false;
@@ -197,19 +198,29 @@ export class GridStackEngine {
if (Number.isNaN(node.width)) { node.width = defaults.width; }
if (Number.isNaN(node.height)) { node.height = defaults.height; }
+ if (node.maxWidth) { node.width = Math.min(node.width, node.maxWidth); }
+ if (node.maxHeight) { node.height = Math.min(node.height, node.maxHeight); }
+ if (node.minWidth) { node.width = Math.max(node.width, node.minWidth); }
+ if (node.minHeight) { node.height = Math.max(node.height, node.minHeight); }
+
if (node.width > this.column) {
node.width = this.column;
} else if (node.width < 1) {
node.width = 1;
}
- if (node.height < 1) {
+ if (this.maxRow && node.height > this.maxRow) {
+ node.height = this.maxRow;
+ } else if (node.height < 1) {
node.height = 1;
}
if (node.x < 0) {
node.x = 0;
}
+ if (node.y < 0) {
+ node.y = 0;
+ }
if (node.x + node.width > this.column) {
if (resizing) {
@@ -218,9 +229,12 @@ export class GridStackEngine {
node.x = this.column - node.width;
}
}
-
- if (node.y < 0) {
- node.y = 0;
+ if (this.maxRow && node.y + node.height > this.maxRow) {
+ if (resizing) {
+ node.height = this.maxRow - node.y;
+ } else {
+ node.y = this.maxRow - node.height;
+ }
}
return node;
@@ -263,11 +277,6 @@ export class GridStackEngine {
public addNode(node: GridStackNode, triggerAddEvent?: boolean) {
node = this.prepareNode(node);
- if (node.maxWidth) { node.width = Math.min(node.width, node.maxWidth); }
- if (node.maxHeight) { node.height = Math.min(node.height, node.maxHeight); }
- if (node.minWidth) { node.width = Math.max(node.width, node.minWidth); }
- if (node.minHeight) { node.height = Math.max(node.height, node.minHeight); }
-
node._id = node._id || GridStackEngine._idSeq++;
if (node.autoPosition) {
@@ -393,34 +402,27 @@ export class GridStackEngine {
}
public moveNode(node: GridStackNode, x: number, y: number, width?: number, height?: number, noPack?: boolean): GridStackNode {
+ if (node.locked) { return null; }
if (typeof x !== 'number') { x = node.x; }
if (typeof y !== 'number') { y = node.y; }
if (typeof width !== 'number') { width = node.width; }
if (typeof height !== 'number') { height = node.height; }
- if (node.maxWidth) { width = Math.min(width, node.maxWidth); }
- if (node.maxHeight) { height = Math.min(height, node.maxHeight); }
- if (node.minWidth) { width = Math.max(width, node.minWidth); }
- if (node.minHeight) { height = Math.max(height, node.minHeight); }
-
- if (node.x === x && node.y === y && node.width === width && node.height === height) {
- return node;
+ // constrain the passed in values and check if we're still changing our node
+ let resizing = (node.width !== width || node.height !== height);
+ let nn: GridStackNode = { x, y, width, height,
+ maxWidth: node.maxWidth, maxHeight: node.maxHeight, minWidth: node.minWidth, minHeight: node.minHeight};
+ nn = this.prepareNode(nn, resizing);
+ if (node.x === nn.x && node.y === nn.y && node.width === nn.width && node.height === nn.height) {
+ return null;
}
- let resizing = node.width !== width;
node._dirty = true;
- node.x = x;
- node.y = y;
- node.width = width;
- node.height = height;
-
- node._lastTriedX = x;
- node._lastTriedY = y;
- node._lastTriedWidth = width;
- node._lastTriedHeight = height;
-
- node = this.prepareNode(node, resizing);
+ node.x = node._lastTriedX = nn.x;
+ node.y = node._lastTriedY = nn.y;
+ node.width = node._lastTriedWidth = nn.width;
+ node.height = node._lastTriedHeight = nn.height;
this._fixCollisions(node);
if (!noPack) {
diff --git a/src/gridstack.ts b/src/gridstack.ts
index 26ebbceea..891be845e 100644
--- a/src/gridstack.ts
+++ b/src/gridstack.ts
@@ -119,7 +119,7 @@ export class GridStack {
let grids: GridStack[] = [];
getGridElements(selector).forEach(el => {
if (!el.gridstack) {
- el.gridstack = new GridStack(el, options);
+ el.gridstack = new GridStack(el, Utils.clone(options));
}
grids.push(el.gridstack);
});
@@ -336,7 +336,7 @@ export class GridStack {
/**
- * Creates new widget and returns it.
+ * add a new widget and returns it.
*
* Widget will be always placed even if result height is more than actual grid height.
* You need to use willItFit method before calling addWidget for additional check.
@@ -344,44 +344,19 @@ export class GridStack {
*
* @example
* let grid = GridStack.init();
- * grid.addWidget(el, {width: 3, autoPosition: true});
+ * grid.addWidget('', {width: 3});
*
- * @param el widget to add
- * @param options widget position/size options (optional)
+ * @param el html element or string definition to add
+ * @param options widget position/size options (optional) - see GridStackWidget
*/
- public addWidget(el: GridStackElement, options? : GridstackWidget): HTMLElement;
-
- /**
- * Creates new widget and returns it.
- * Legacy: Spelled out version of the widgets options, recommend use new version instead.
- *
- * @example
- * let grid = GridStack.init();
- * grid.addWidget(el, 0, 0, 3, 2, true);
- *
- * @param el widget to add
- * @param x widget position x (optional)
- * @param y widget position y (optional)
- * @param width widget dimension width (optional)
- * @param height widget dimension height (optional)
- * @param autoPosition if true then x, y parameters will be ignored and widget will be places on the first available position (optional)
- * @param minWidth minimum width allowed during resize/creation (optional)
- * @param maxWidth maximum width allowed during resize/creation (optional)
- * @param minHeight minimum height allowed during resize/creation (optional)
- * @param maxHeight maximum height allowed during resize/creation (optional)
- * @param id value for `data-gs-id` (optional)
- */
- public addWidget(el: GridStackElement, x? : number | GridstackWidget, y?: number, width?: number, height?: number, autoPosition?: boolean,
- minWidth?: number, maxWidth?: number, minHeight?: number, maxHeight?: number, id?: numberOrString): HTMLElement {
- // new way of calling with an object - make sure all items have been properly initialized
- if (x === undefined || typeof x === 'object') {
- // Tempting to initialize the passed in opt with default and valid values, but this break knockout demos
- // as the actual value are filled in when _prepareElement() calls el.attr('data-gs-xyz) before adding the node.
- // opt = this.engine.prepareNode(opt);
- x = (x || {}) as GridstackWidget;
- } else {
- // old legacy way of calling with items spelled out - call us back with single object instead (so we can properly initialized values)
- return this.addWidget(el, { x, y, width, height, autoPosition, minWidth, maxWidth, minHeight, maxHeight, id });
+ public addWidget(el: GridStackElement, options?: GridstackWidget): GridItemHTMLElement {
+
+ // support legacy call for now ?
+ if (arguments.length > 2) {
+ console.warn('gridstack.ts: `addWidget(el, x, y, width...)` is deprecated. Use `addWidget(el, {x, y, width,...})`. It will be removed soon');
+ let a = arguments, i = 1,
+ opt: GridstackWidget = { x:a[i++], y:a[i++], width:a[i++], height:a[i++], autoPosition:a[i++], minWidth:a[i++], maxWidth:a[i++], minHeight:a[i++], maxHeight:a[i++], id:a[i++] };
+ return this.addWidget(el, opt);
}
if (typeof el === 'string') {
@@ -390,9 +365,13 @@ export class GridStack {
el = doc.body.children[0] as HTMLElement;
}
- this._writeAttr(el, x);
- this.el.appendChild(el);
+ // Tempting to initialize the passed in opt with default and valid values, but this break knockout demos
+ // as the actual value are filled in when _prepareElement() calls el.getAttribute('data-gs-xyz) before adding the node.
+ if (options) {
+ this._writeAttr(el, options);
+ }
+ this.el.appendChild(el);
return this.makeWidget(el);
}
@@ -595,6 +574,11 @@ export class GridStack {
* enable/disable floating widgets (default: `false`) See [example](http://gridstackjs.com/demo/float.html)
*/
public float(val: boolean) {
+ if (val === undefined) {
+ // TODO: should we support and/or change signature ? figure this soon...
+ console.warn('gridstack.ts: getter `float()` is deprecated in 2.x and has been replaced by `getFloat()`. It will be **completely** removed soon');
+ return this.getFloat();
+ }
this.engine.float = val;
this._triggerChangeEvent();
}
@@ -603,7 +587,7 @@ export class GridStack {
* get the current float mode
*/
public getFloat(): boolean {
- return this.engine.float || false;
+ return this.engine.float;
}
/**
@@ -672,7 +656,7 @@ export class GridStack {
* grid.el.appendChild('');
* grid.makeWidget('gsi-1');
*/
- public makeWidget(els: GridStackElement): HTMLElement {
+ public makeWidget(els: GridStackElement): GridItemHTMLElement {
let el = getElement(els);
this._prepareElement(el, true);
this._updateContainerHeight();
@@ -1008,8 +992,8 @@ export class GridStack {
* will be places on the first available position
*
* @example
- * if (grid.willItFit(newNode.x, newNode.y, newNode.width, newNode.height, true)) {
- * grid.addWidget(newNode.el, newNode.x, newNode.y, newNode.width, newNode.height, true);
+ * if (grid.willItFit(newNode.x, newNode.y, newNode.width, newNode.height, newNode.autoPosition)) {
+ * grid.addWidget(newNode.el, newNode);
* } else {
* alert('Not enough free space to place the widget');
* }
@@ -1400,7 +1384,8 @@ export class GridStack {
}
/** call to write any default attributes back to element */
- private _writeAttr(el: HTMLElement, node: GridstackWidget = {}) {
+ private _writeAttr(el: HTMLElement, node: GridstackWidget) {
+ if (!node) return;
this._writeAttrs(el, node.x, node.y, node.width, node.height);
if (node.autoPosition) {
diff --git a/src/types.ts b/src/types.ts
index 578175d9f..79921ffd2 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -203,7 +203,7 @@ export interface DDResizeOpt {
/** Drag&Drop remove options */
export interface DDRemoveOpt {
- /** class that be removed default?: '.' + opts.itemClass */
+ /** class that can be removed (default?: '.' + opts.itemClass) */
accept?: string;
}