From 94e1341ea09f8cd5dfba62defbbb92c6bd1a6e9a Mon Sep 17 00:00:00 2001 From: Alain Dumesny Date: Mon, 6 Jul 2020 23:25:00 -0700 Subject: [PATCH] TS: #723 #726 `margin` to replace `verticalMargin` * complete re-write how we size/position items dealing with margin * we now have a single `margin` grid option which will set all 4 sides instead of one in code nad one in CSS * also have `marginTop/Bottom/Left/Right` if more precise setting is required * greatly reduced the layout code as margin are now inside the grid-item (affects content) * fixed code so `cellHeight: 'auto'` (now the default) will create real square cells (used to be off due to margin) * grid will now have consistant spacing (above/below first/last rows) --- README.md | 7 +- demo/nested.html | 3 +- doc/CHANGES.md | 4 +- doc/README.md | 49 +- .../1017-items-no-x-y-for-autoPosition.html | 2 +- spec/e2e/html/810-many-columns.css | 601 ++++++++++++++---- spec/e2e/html/810-many-columns.html | 8 +- spec/gridstack-spec.ts | 84 +-- src/gridstack.scss | 22 +- src/gridstack.ts | 226 ++++--- src/types.ts | 26 +- src/utils.ts | 10 +- 12 files changed, 714 insertions(+), 328 deletions(-) diff --git a/README.md b/README.md index 81ba0eca5..f08a94f52 100644 --- a/README.md +++ b/README.md @@ -334,14 +334,15 @@ make sure to read v1.0.0 migration first! v2.x is a Typescript rewrite of 1.x, removing all jquery events, using classes and overall code cleanup. Your code might need to change from 1.x -1. In general methods that used no args (getter) vs setter are not used in Typescript. -Also legacy methods that used to take tons of parameters will now take a single object (typically `GridstackOptions` or `GridStackWidget`). +1. In general methods that used no args (getter) vs setter are not used in Typescript when the arguments differ. +Also legacy methods that used to take many parameters will now take a single object (typically `GridstackOptions` or `GridStackWidget`). ``` removed `addWidget(el, x, y, width, ...)` --> use the widget options version instead `addWidget(el, {with, ...})` `float()` to get value --> `getFloat()` 'cellHeight()` to get value --> `getCellHeight()` -'verticalMargin()` to get value --> `getVerticalMargin()` +'verticalMargin' is now 'margin' grid options and applies to all 4 sides. +'verticalMargin()` to get value --> `getMargin()` ``` 2. event signatures are generic and not jquery-ui dependent anymore. `gsresizestop` has been removed as `resizestop|dragstop` are now called **after** the DOm attributes have been updated. diff --git a/demo/nested.html b/demo/nested.html index bd2f3f233..ef4efc3c4 100644 --- a/demo/nested.html +++ b/demo/nested.html @@ -57,7 +57,8 @@

Nested grids demo

let nestOptions = { acceptWidgets: '.grid-stack-item.sub', // only pink sub items can be inserted, otherwise grid-items causes all sort of issues dragOut: true, // let us drag them out! - disableOneColumnMode: true // nested are small, but still want N columns + disableOneColumnMode: true, // nested are small, but still want N columns + margin: 1 }; GridStack.init(null, '.grid-stack.top'); let grid1 = GridStack.init(nestOptions, '.grid-stack.nested1'); diff --git a/doc/CHANGES.md b/doc/CHANGES.md index aa6a6dc71..181a80f42 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -40,6 +40,8 @@ Change log - add `getGridItems()` to return list of HTML grid items - add `{dragIn | dragInOptions}` grid attributes to handle external drag&drop items - add `save()` and `restore()` to serialize grids from JSON, saving all attributes (not just w,h,x,y) [1286](https://github.com/gridstack/gridstack.js/issues/1286) +- add `margin` to replace `verticalMargin` which affects both dimensions in code, rather than one in code the other in CSS. +You can now have perfect square cells (default) [723](https://github.com/gridstack/gridstack.js/issues/723) - fix [1299](https://github.com/gridstack/gridstack.js/pull/1299) many columns round-off error ## 1.1.2 (2020-05-17) @@ -210,7 +212,7 @@ thanks [@ermcgrat](https://github.com/ermcgrat) and others for pointing out code ## v0.2.5 (2016-03-02) - update names to respect js naming convention. -- `cellHeight` and `verticalMargin` can now be string (e.g. '3em', '20px') (Thanks to @jlowcs). +- `cellHeight` and `margin` can now be string (e.g. '3em', '20px') (Thanks to @jlowcs). - add `maxWidth`/`maxHeight` methods. - add `enableMove`/`enableResize` methods. - fix window resize issue [#331](https://github.com/gridstack/gridstack.js/issues/331)). diff --git a/doc/README.md b/doc/README.md index 51352160b..ac7cff0fa 100644 --- a/doc/README.md +++ b/doc/README.md @@ -24,7 +24,7 @@ gridstack.js API - [addWidget(el, [options])](#addwidgetel-options) - [batchUpdate()](#batchupdate) - [compact()](#compact) - - [cellHeight(val, noUpdate)](#cellheightval-noupdate) + - [cellHeight(val: number, update = true)](#cellheightval-number-update--true) - [cellWidth()](#cellwidth) - [commit()](#commit) - [column(column, doNotPropagate)](#columncolumn-donotpropagate) @@ -37,9 +37,11 @@ gridstack.js API - [getCellHeight()](#getcellheight) - [getCellFromPixel(position[, useOffset])](#getcellfrompixelposition-useoffset) - [getGridItems(): GridItemHTMLElement[]](#getgriditems-griditemhtmlelement) + - [getMargin()](#getmargin) - [isAreaEmpty(x, y, width, height)](#isareaemptyx-y-width-height) - [locked(el, val)](#lockedel-val) - [makeWidget(el)](#makewidgetel) + - [margin(value: number)](#marginvalue-number) - [maxHeight(el, val)](#maxheightel-val) - [minHeight(el, val)](#minheightel-val) - [maxWidth(el, val)](#maxwidthel-val) @@ -55,8 +57,6 @@ gridstack.js API - [setAnimation(doAnimate)](#setanimationdoanimate) - [setStatic(staticValue)](#setstaticstaticvalue) - [update(el, x, y, width, height)](#updateel-x-y-width-height) - - [getVerticalMargin()](#getverticalmargin) - - [verticalMargin(value, noUpdate)](#verticalmarginvalue-noupdate) - [willItFit(x, y, width, height, autoPosition)](#willitfitx-y-width-height-autoposition) - [Utils](#utils) - [GridStack.Utils.sort(nodes[, dir[, width]])](#gridstackutilssortnodes-dir-width) @@ -76,11 +76,11 @@ gridstack.js API See [example](http://gridstack.github.io/gridstack.js/demo/advance.html) - `animate` - turns animation on (default: `false`) - `auto` - if `false` gridstack will not initialize existing items (default: `true`) -- `cellHeight` - one cell height (default: `60`). Can be: +- `cellHeight` - one cell height (default: `auto`). Can be: * an integer (px) - * a string (ex: '100px', '10em', '10rem', '10%') + * a string (ex: '100px', '10em', '10rem', '10%', `10vh') * 0 or null, in which case the library will not generate styles for rows. Everything must be defined in CSS files. - * `'auto'` - height will be calculated cell square initially. + * `'auto'` - height will be square cells initially. - `column` - number of columns (default: `12`) which can change on the fly with `column(N)` as well. See [example](http://gridstackjs.com/demo/column.html) - `ddPlugin` - class that implement drag'n'drop functionality for gridstack. If `false` grid will be static. (default: `null` - first available plugin will be used) - `disableDrag` - disallows dragging of widgets (default: `false`). @@ -94,6 +94,13 @@ gridstack.js API - `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`) - `itemClass` - widget class (default: `'grid-stack-item'`) +- `margin` - gap size around grid item and content (default: `10`). Can be: + * an integer (px) + * a string (ex: '2em', '20px', '2rem') +- `marginTop`: numberOrString - can set individual settings (defaults to `margin`) +- `marginRight`: numberOrString +- `marginBottom`: numberOrString +- `marginLeft`: numberOrString - `maxRow` - maximum rows amount. Default is `0` which means no max. - `minRow` - minimum rows amount which is handy to prevent grid from collapsing when empty. Default is `0`. You can also do this with `min-height` CSS attribute on the grid div in pixels, which will round to the closest row. - `minWidth` - minimal width. If grid width is less than or equal to, grid will be shown in one-column mode (default: `768`) @@ -106,9 +113,6 @@ gridstack.js API - `row` - fix grid number of rows. This is a shortcut of writing `minRow:N, maxRow:N`. (default `0` no constrain) - `rtl` - if `true` turns grid to RTL. Possible values are `true`, `false`, `'auto'` (default: `'auto'`) See [example](http://gridstackjs.com/demo/rtl.html) - `staticGrid` - removes drag&drop&resize (default `false`). If `true` widgets are not movable/resizable by the user, but code can still move and oneColumnMode will still work. You don't even need jQueryUI draggable/resizable. A CSS class `grid-stack-static` is also added to the container. -- `verticalMargin` - vertical gap size (default: `20`). Can be: - * an integer (px) - * a string (ex: '2em', '20px', '2rem') ## Grid attributes @@ -273,9 +277,9 @@ starts batch updates. You will see no changes until `commit()` method is called. re-layout grid items to reclaim any empty space. -### cellHeight(val, noUpdate) +### cellHeight(val: number, update = true) -Update current cell height. This method rebuilds an internal CSS stylesheet (unless optional noUpdate=true). Note: You can expect performance issues if +Update current cell height. This method rebuilds an internal CSS stylesheet (unless optional update=false). Note: You can expect performance issues if call this method too often. ```js @@ -284,7 +288,7 @@ grid.cellHeight(grid.cellWidth() * 1.2); ### cellWidth() -Gets current cell width. +Gets current cell width (grid width / # of columns). ### commit() @@ -370,6 +374,10 @@ Returns an object with properties `x` and `y` i.e. the column and row in the gri Return list of GridItem HTML dom elements (excluding temporary placeholder) +### getMargin() + +returns current margin value. + ### isAreaEmpty(x, y, width, height) Checks if specified area is empty. @@ -396,6 +404,12 @@ grid.el.appendChild('
let options = { cellHeight: 80, - verticalMargin: 10, + margin: 5, float: true }; GridStack.init(options); diff --git a/spec/e2e/html/810-many-columns.css b/spec/e2e/html/810-many-columns.css index 03c4f18d5..beeedc645 100644 --- a/spec/e2e/html/810-many-columns.css +++ b/spec/e2e/html/810-many-columns.css @@ -16,366 +16,725 @@ /* override gridstack,css */ .grid-stack > .grid-stack-item { - min-width: 3.3333333333%; + min-width: 1.6666666667%; } - .grid-stack > .grid-stack-item[data-gs-width="1"] { - width: 3.3333333333%; + width: 1.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="1"] { - left: 3.3333333333%; + left: 1.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="1"] { - min-width: 3.3333333333%; + min-width: 1.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="1"] { - max-width: 3.3333333333%; + max-width: 1.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="2"] { - width: 6.6666666667%; + width: 3.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="2"] { - left: 6.6666666667%; + left: 3.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="2"] { - min-width: 6.6666666667%; + min-width: 3.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="2"] { - max-width: 6.6666666667%; + max-width: 3.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="3"] { - width: 10%; + width: 5%; } .grid-stack > .grid-stack-item[data-gs-x="3"] { - left: 10%; + left: 5%; } .grid-stack > .grid-stack-item[data-gs-min-width="3"] { - min-width: 10%; + min-width: 5%; } .grid-stack > .grid-stack-item[data-gs-max-width="3"] { - max-width: 10%; + max-width: 5%; } .grid-stack > .grid-stack-item[data-gs-width="4"] { - width: 13.3333333333%; + width: 6.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="4"] { - left: 13.3333333333%; + left: 6.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="4"] { - min-width: 13.3333333333%; + min-width: 6.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="4"] { - max-width: 13.3333333333%; + max-width: 6.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="5"] { - width: 16.6666666667%; + width: 8.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="5"] { - left: 16.6666666667%; + left: 8.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="5"] { - min-width: 16.6666666667%; + min-width: 8.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="5"] { - max-width: 16.6666666667%; + max-width: 8.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="6"] { - width: 20%; + width: 10%; } .grid-stack > .grid-stack-item[data-gs-x="6"] { - left: 20%; + left: 10%; } .grid-stack > .grid-stack-item[data-gs-min-width="6"] { - min-width: 20%; + min-width: 10%; } .grid-stack > .grid-stack-item[data-gs-max-width="6"] { - max-width: 20%; + max-width: 10%; } .grid-stack > .grid-stack-item[data-gs-width="7"] { - width: 23.3333333333%; + width: 11.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="7"] { - left: 23.3333333333%; + left: 11.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="7"] { - min-width: 23.3333333333%; + min-width: 11.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="7"] { - max-width: 23.3333333333%; + max-width: 11.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="8"] { - width: 26.6666666667%; + width: 13.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="8"] { - left: 26.6666666667%; + left: 13.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="8"] { - min-width: 26.6666666667%; + min-width: 13.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="8"] { - max-width: 26.6666666667%; + max-width: 13.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="9"] { - width: 30%; + width: 15%; } .grid-stack > .grid-stack-item[data-gs-x="9"] { - left: 30%; + left: 15%; } .grid-stack > .grid-stack-item[data-gs-min-width="9"] { - min-width: 30%; + min-width: 15%; } .grid-stack > .grid-stack-item[data-gs-max-width="9"] { - max-width: 30%; + max-width: 15%; } .grid-stack > .grid-stack-item[data-gs-width="10"] { - width: 33.3333333333%; + width: 16.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="10"] { - left: 33.3333333333%; + left: 16.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="10"] { - min-width: 33.3333333333%; + min-width: 16.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="10"] { - max-width: 33.3333333333%; + max-width: 16.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="11"] { - width: 36.6666666667%; + width: 18.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="11"] { - left: 36.6666666667%; + left: 18.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="11"] { - min-width: 36.6666666667%; + min-width: 18.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="11"] { - max-width: 36.6666666667%; + max-width: 18.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="12"] { - width: 40%; + width: 20%; } .grid-stack > .grid-stack-item[data-gs-x="12"] { - left: 40%; + left: 20%; } .grid-stack > .grid-stack-item[data-gs-min-width="12"] { - min-width: 40%; + min-width: 20%; } .grid-stack > .grid-stack-item[data-gs-max-width="12"] { - max-width: 40%; + max-width: 20%; } .grid-stack > .grid-stack-item[data-gs-width="13"] { - width: 43.3333333333%; + width: 21.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="13"] { - left: 43.3333333333%; + left: 21.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="13"] { - min-width: 43.3333333333%; + min-width: 21.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="13"] { - max-width: 43.3333333333%; + max-width: 21.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="14"] { - width: 46.6666666667%; + width: 23.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="14"] { - left: 46.6666666667%; + left: 23.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="14"] { - min-width: 46.6666666667%; + min-width: 23.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="14"] { - max-width: 46.6666666667%; + max-width: 23.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="15"] { - width: 50%; + width: 25%; } .grid-stack > .grid-stack-item[data-gs-x="15"] { - left: 50%; + left: 25%; } .grid-stack > .grid-stack-item[data-gs-min-width="15"] { - min-width: 50%; + min-width: 25%; } .grid-stack > .grid-stack-item[data-gs-max-width="15"] { - max-width: 50%; + max-width: 25%; } .grid-stack > .grid-stack-item[data-gs-width="16"] { - width: 53.3333333333%; + width: 26.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="16"] { - left: 53.3333333333%; + left: 26.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="16"] { - min-width: 53.3333333333%; + min-width: 26.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="16"] { - max-width: 53.3333333333%; + max-width: 26.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="17"] { - width: 56.6666666667%; + width: 28.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="17"] { - left: 56.6666666667%; + left: 28.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="17"] { - min-width: 56.6666666667%; + min-width: 28.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="17"] { - max-width: 56.6666666667%; + max-width: 28.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="18"] { - width: 60%; + width: 30%; } .grid-stack > .grid-stack-item[data-gs-x="18"] { - left: 60%; + left: 30%; } .grid-stack > .grid-stack-item[data-gs-min-width="18"] { - min-width: 60%; + min-width: 30%; } .grid-stack > .grid-stack-item[data-gs-max-width="18"] { - max-width: 60%; + max-width: 30%; } .grid-stack > .grid-stack-item[data-gs-width="19"] { - width: 63.3333333333%; + width: 31.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="19"] { - left: 63.3333333333%; + left: 31.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="19"] { - min-width: 63.3333333333%; + min-width: 31.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="19"] { - max-width: 63.3333333333%; + max-width: 31.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="20"] { - width: 66.6666666667%; + width: 33.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="20"] { - left: 66.6666666667%; + left: 33.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="20"] { - min-width: 66.6666666667%; + min-width: 33.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="20"] { - max-width: 66.6666666667%; + max-width: 33.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="21"] { - width: 70%; + width: 35%; } .grid-stack > .grid-stack-item[data-gs-x="21"] { - left: 70%; + left: 35%; } .grid-stack > .grid-stack-item[data-gs-min-width="21"] { - min-width: 70%; + min-width: 35%; } .grid-stack > .grid-stack-item[data-gs-max-width="21"] { - max-width: 70%; + max-width: 35%; } .grid-stack > .grid-stack-item[data-gs-width="22"] { - width: 73.3333333333%; + width: 36.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="22"] { - left: 73.3333333333%; + left: 36.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="22"] { - min-width: 73.3333333333%; + min-width: 36.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="22"] { - max-width: 73.3333333333%; + max-width: 36.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="23"] { - width: 76.6666666667%; + width: 38.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="23"] { - left: 76.6666666667%; + left: 38.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="23"] { - min-width: 76.6666666667%; + min-width: 38.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="23"] { - max-width: 76.6666666667%; + max-width: 38.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="24"] { - width: 80%; + width: 40%; } .grid-stack > .grid-stack-item[data-gs-x="24"] { - left: 80%; + left: 40%; } .grid-stack > .grid-stack-item[data-gs-min-width="24"] { - min-width: 80%; + min-width: 40%; } .grid-stack > .grid-stack-item[data-gs-max-width="24"] { - max-width: 80%; + max-width: 40%; } .grid-stack > .grid-stack-item[data-gs-width="25"] { - width: 83.3333333333%; + width: 41.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="25"] { - left: 83.3333333333%; + left: 41.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="25"] { - min-width: 83.3333333333%; + min-width: 41.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="25"] { - max-width: 83.3333333333%; + max-width: 41.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="26"] { - width: 86.6666666667%; + width: 43.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="26"] { - left: 86.6666666667%; + left: 43.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="26"] { - min-width: 86.6666666667%; + min-width: 43.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="26"] { - max-width: 86.6666666667%; + max-width: 43.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="27"] { - width: 90%; + width: 45%; } .grid-stack > .grid-stack-item[data-gs-x="27"] { - left: 90%; + left: 45%; } .grid-stack > .grid-stack-item[data-gs-min-width="27"] { - min-width: 90%; + min-width: 45%; } .grid-stack > .grid-stack-item[data-gs-max-width="27"] { - max-width: 90%; + max-width: 45%; } .grid-stack > .grid-stack-item[data-gs-width="28"] { - width: 93.3333333333%; + width: 46.6666666667%; } .grid-stack > .grid-stack-item[data-gs-x="28"] { - left: 93.3333333333%; + left: 46.6666666667%; } .grid-stack > .grid-stack-item[data-gs-min-width="28"] { - min-width: 93.3333333333%; + min-width: 46.6666666667%; } .grid-stack > .grid-stack-item[data-gs-max-width="28"] { - max-width: 93.3333333333%; + max-width: 46.6666666667%; } .grid-stack > .grid-stack-item[data-gs-width="29"] { - width: 96.6666666667%; + width: 48.3333333333%; } .grid-stack > .grid-stack-item[data-gs-x="29"] { - left: 96.6666666667%; + left: 48.3333333333%; } .grid-stack > .grid-stack-item[data-gs-min-width="29"] { - min-width: 96.6666666667%; + min-width: 48.3333333333%; } .grid-stack > .grid-stack-item[data-gs-max-width="29"] { - max-width: 96.6666666667%; + max-width: 48.3333333333%; } .grid-stack > .grid-stack-item[data-gs-width="30"] { - width: 100%; + width: 50%; } .grid-stack > .grid-stack-item[data-gs-x="30"] { - left: 100%; + left: 50%; } .grid-stack > .grid-stack-item[data-gs-min-width="30"] { - min-width: 100%; + min-width: 50%; } .grid-stack > .grid-stack-item[data-gs-max-width="30"] { + max-width: 50%; + } + .grid-stack > .grid-stack-item[data-gs-width="31"] { + width: 51.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="31"] { + left: 51.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="31"] { + min-width: 51.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="31"] { + max-width: 51.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="32"] { + width: 53.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="32"] { + left: 53.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="32"] { + min-width: 53.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="32"] { + max-width: 53.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="33"] { + width: 55%; + } + .grid-stack > .grid-stack-item[data-gs-x="33"] { + left: 55%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="33"] { + min-width: 55%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="33"] { + max-width: 55%; + } + .grid-stack > .grid-stack-item[data-gs-width="34"] { + width: 56.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="34"] { + left: 56.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="34"] { + min-width: 56.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="34"] { + max-width: 56.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="35"] { + width: 58.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="35"] { + left: 58.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="35"] { + min-width: 58.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="35"] { + max-width: 58.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="36"] { + width: 60%; + } + .grid-stack > .grid-stack-item[data-gs-x="36"] { + left: 60%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="36"] { + min-width: 60%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="36"] { + max-width: 60%; + } + .grid-stack > .grid-stack-item[data-gs-width="37"] { + width: 61.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="37"] { + left: 61.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="37"] { + min-width: 61.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="37"] { + max-width: 61.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="38"] { + width: 63.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="38"] { + left: 63.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="38"] { + min-width: 63.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="38"] { + max-width: 63.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="39"] { + width: 65%; + } + .grid-stack > .grid-stack-item[data-gs-x="39"] { + left: 65%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="39"] { + min-width: 65%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="39"] { + max-width: 65%; + } + .grid-stack > .grid-stack-item[data-gs-width="40"] { + width: 66.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="40"] { + left: 66.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="40"] { + min-width: 66.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="40"] { + max-width: 66.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="41"] { + width: 68.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="41"] { + left: 68.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="41"] { + min-width: 68.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="41"] { + max-width: 68.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="42"] { + width: 70%; + } + .grid-stack > .grid-stack-item[data-gs-x="42"] { + left: 70%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="42"] { + min-width: 70%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="42"] { + max-width: 70%; + } + .grid-stack > .grid-stack-item[data-gs-width="43"] { + width: 71.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="43"] { + left: 71.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="43"] { + min-width: 71.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="43"] { + max-width: 71.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="44"] { + width: 73.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="44"] { + left: 73.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="44"] { + min-width: 73.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="44"] { + max-width: 73.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="45"] { + width: 75%; + } + .grid-stack > .grid-stack-item[data-gs-x="45"] { + left: 75%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="45"] { + min-width: 75%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="45"] { + max-width: 75%; + } + .grid-stack > .grid-stack-item[data-gs-width="46"] { + width: 76.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="46"] { + left: 76.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="46"] { + min-width: 76.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="46"] { + max-width: 76.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="47"] { + width: 78.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="47"] { + left: 78.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="47"] { + min-width: 78.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="47"] { + max-width: 78.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="48"] { + width: 80%; + } + .grid-stack > .grid-stack-item[data-gs-x="48"] { + left: 80%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="48"] { + min-width: 80%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="48"] { + max-width: 80%; + } + .grid-stack > .grid-stack-item[data-gs-width="49"] { + width: 81.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="49"] { + left: 81.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="49"] { + min-width: 81.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="49"] { + max-width: 81.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="50"] { + width: 83.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="50"] { + left: 83.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="50"] { + min-width: 83.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="50"] { + max-width: 83.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="51"] { + width: 85%; + } + .grid-stack > .grid-stack-item[data-gs-x="51"] { + left: 85%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="51"] { + min-width: 85%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="51"] { + max-width: 85%; + } + .grid-stack > .grid-stack-item[data-gs-width="52"] { + width: 86.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="52"] { + left: 86.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="52"] { + min-width: 86.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="52"] { + max-width: 86.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="53"] { + width: 88.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="53"] { + left: 88.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="53"] { + min-width: 88.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="53"] { + max-width: 88.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="54"] { + width: 90%; + } + .grid-stack > .grid-stack-item[data-gs-x="54"] { + left: 90%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="54"] { + min-width: 90%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="54"] { + max-width: 90%; + } + .grid-stack > .grid-stack-item[data-gs-width="55"] { + width: 91.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="55"] { + left: 91.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="55"] { + min-width: 91.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="55"] { + max-width: 91.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="56"] { + width: 93.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="56"] { + left: 93.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="56"] { + min-width: 93.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="56"] { + max-width: 93.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="57"] { + width: 95%; + } + .grid-stack > .grid-stack-item[data-gs-x="57"] { + left: 95%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="57"] { + min-width: 95%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="57"] { + max-width: 95%; + } + .grid-stack > .grid-stack-item[data-gs-width="58"] { + width: 96.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-x="58"] { + left: 96.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="58"] { + min-width: 96.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="58"] { + max-width: 96.6666666667%; + } + .grid-stack > .grid-stack-item[data-gs-width="59"] { + width: 98.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-x="59"] { + left: 98.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="59"] { + min-width: 98.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="59"] { + max-width: 98.3333333333%; + } + .grid-stack > .grid-stack-item[data-gs-width="60"] { + width: 100%; + } + .grid-stack > .grid-stack-item[data-gs-x="60"] { + left: 100%; + } + .grid-stack > .grid-stack-item[data-gs-min-width="60"] { + min-width: 100%; + } + .grid-stack > .grid-stack-item[data-gs-max-width="60"] { max-width: 100%; } \ No newline at end of file diff --git a/spec/e2e/html/810-many-columns.html b/spec/e2e/html/810-many-columns.html index 3bfbc210d..e6f13a00c 100644 --- a/spec/e2e/html/810-many-columns.html +++ b/spec/e2e/html/810-many-columns.html @@ -20,13 +20,13 @@

Many Columns demo

- diff --git a/spec/gridstack-spec.ts b/spec/gridstack-spec.ts index 4fbb90886..faff00466 100644 --- a/spec/gridstack-spec.ts +++ b/spec/gridstack-spec.ts @@ -126,7 +126,7 @@ describe('gridstack', function() { it('should return {x: 2, y: 5}.', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); let pixel = {top: 500, left: 200}; @@ -152,7 +152,7 @@ describe('gridstack', function() { it('should return 1/12th of container width.', function() { let options = { cellHeight: 80, - verticalMargin: 10, + margin: 5, column: 12 }; let grid = GridStack.init(options); @@ -162,7 +162,7 @@ describe('gridstack', function() { it('should return 1/10th of container width.', function() { let options = { cellHeight: 80, - verticalMargin: 10, + margin: 5, column: 10 }; let grid = GridStack.init(options); @@ -180,10 +180,10 @@ describe('gridstack', function() { }); it('should start at 80 then become 120', function() { let cellHeight = 80; - let verticalMargin = 10; + let margin = 5; let options = { cellHeight: cellHeight, - verticalMargin: verticalMargin, + margin: margin, column: 12 }; let grid = GridStack.init(options); @@ -193,21 +193,21 @@ describe('gridstack', function() { expect(grid.getRow()).toBe(rows); expect(grid.getCellHeight()).toBe(cellHeight); - expect(parseInt(container.css('height'))).toBe(rows * cellHeight + (rows-1) * verticalMargin); + expect(parseInt(container.css('height'))).toBe(rows * cellHeight + (rows-1) * margin); grid.cellHeight( grid.getCellHeight() ); // should be no-op expect(grid.getCellHeight()).toBe(cellHeight); - expect(parseInt(container.css('height'))).toBe(rows * cellHeight + (rows-1) * verticalMargin); + expect(parseInt(container.css('height'))).toBe(rows * cellHeight + (rows-1) * margin); cellHeight = 120; // should change and CSS actual height grid.cellHeight( cellHeight ); expect(grid.getCellHeight()).toBe(cellHeight); - expect(parseInt(container.css('height'))).toBe(rows * cellHeight + (rows-1) * verticalMargin); + expect(parseInt(container.css('height'))).toBe(rows * cellHeight + (rows-1) * margin); cellHeight = 20; // should change and CSS actual height grid.cellHeight( cellHeight ); expect(grid.getCellHeight()).toBe(cellHeight); - expect(parseInt(container.css('height'))).toBe(rows * cellHeight + (rows-1) * verticalMargin); + expect(parseInt(container.css('height'))).toBe(rows * cellHeight + (rows-1) * margin); }); it('should be square', function() { @@ -611,7 +611,7 @@ describe('gridstack', function() { it('should set return false.', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); let shouldBeFalse = grid.isAreaEmpty(1, 1, 1, 1); @@ -620,7 +620,7 @@ describe('gridstack', function() { it('should set return true.', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); let shouldBeTrue = grid.isAreaEmpty(5, 5, 1, 1); @@ -696,7 +696,7 @@ describe('gridstack', function() { it('should allow same x, y coordinates for widgets.', function() { let options = { cellHeight: 80, - verticalMargin: 10, + margin: 5, float: true }; let grid = GridStack.init(options); @@ -713,7 +713,7 @@ describe('gridstack', function() { it('should not allow same x, y coordinates for widgets.', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); let items = $('.grid-stack-item'); @@ -953,7 +953,7 @@ describe('gridstack', function() { it('should cleanup gridstack', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); grid.destroy(); @@ -963,7 +963,7 @@ describe('gridstack', function() { it('should cleanup gridstack but leave elements', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); grid.destroy(false); @@ -984,7 +984,7 @@ describe('gridstack', function() { it('should resize widget', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); let items = $('.grid-stack-item'); @@ -1004,7 +1004,7 @@ describe('gridstack', function() { it('should move widget', function() { let options = { cellHeight: 80, - verticalMargin: 10, + margin: 5, float: true }; let grid = GridStack.init(options); @@ -1054,7 +1054,7 @@ describe('gridstack', function() { it('should move and resize widget', function() { let options = { cellHeight: 80, - verticalMargin: 10, + margin: 5, float: true }; let grid = GridStack.init(options); @@ -1067,51 +1067,53 @@ describe('gridstack', function() { }); }); - describe('grid.verticalMargin', function() { + describe('grid.margin', function() { beforeEach(function() { document.body.insertAdjacentHTML('afterbegin', gridstackHTML); }); afterEach(function() { document.body.removeChild(document.getElementById('gs-cont')); }); - it('should return verticalMargin', function() { + it('should return margin', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 10 }; let grid = GridStack.init(options); - let vm = grid.getVerticalMargin(); + let vm = grid.getMargin(); expect(vm).toBe(10); }); - it('should return update verticalMargin', function() { + it('should return update margin', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); - grid.verticalMargin(11); - expect(grid.getVerticalMargin()).toBe(11); + grid.margin(11); + expect(grid.getMargin()).toBe(11); }); it('should do nothing', function() { let options = { cellHeight: 80, - verticalMargin: 10, + margin: 10, }; let grid = GridStack.init(options); - expect(grid.getVerticalMargin()).toBe(10); - grid.verticalMargin(10); - expect(grid.getVerticalMargin()).toBe(10); + expect(grid.getMargin()).toBe(10); + grid.margin(10); + expect(grid.getMargin()).toBe(10); }); + /* it('should not update styles', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid: any = GridStack.init(options); spyOn(grid, '_updateStyles'); - grid.verticalMargin(11, true); + grid.margin(11, false); expect(grid._updateStyles).not.toHaveBeenCalled(); }); + */ }); describe('grid.opts.rtl', function() { @@ -1124,7 +1126,7 @@ describe('gridstack', function() { it('should add grid-stack-rtl class', function() { let options = { cellHeight: 80, - verticalMargin: 10, + margin: 5, rtl: true }; let grid = GridStack.init(options); @@ -1133,7 +1135,7 @@ describe('gridstack', function() { it('should not add grid-stack-rtl class', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); expect($('.grid-stack').hasClass('grid-stack-rtl')).toBe(false); @@ -1150,7 +1152,7 @@ describe('gridstack', function() { it('should enable move for future also', function() { let options = { cellHeight: 80, - verticalMargin: 10, + margin: 5, disableDrag: true }; let grid = GridStack.init(options); @@ -1169,7 +1171,7 @@ describe('gridstack', function() { it('should disable move for existing only', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); let items = $('.grid-stack-item'); @@ -1196,7 +1198,7 @@ describe('gridstack', function() { it('should enable resize', function() { let options = { cellHeight: 80, - verticalMargin: 10, + margin: 5, disableResize: true }; let grid = GridStack.init(options); @@ -1211,7 +1213,7 @@ describe('gridstack', function() { it('should disable resize', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); let items = $('.grid-stack-item'); @@ -1233,7 +1235,7 @@ describe('gridstack', function() { it('should enable movable and resizable', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); let items = $('.grid-stack-item'); @@ -1261,7 +1263,7 @@ describe('gridstack', function() { it('should lock widgets', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); grid.locked('.grid-stack-item', true); @@ -1272,7 +1274,7 @@ describe('gridstack', function() { it('should unlock widgets', function() { let options = { cellHeight: 80, - verticalMargin: 10 + margin: 5 }; let grid = GridStack.init(options); grid.locked('.grid-stack-item', false); diff --git a/src/gridstack.scss b/src/gridstack.scss index a699197da..98f8fbc0a 100644 --- a/src/gridstack.scss +++ b/src/gridstack.scss @@ -6,8 +6,6 @@ */ $gridstack-columns: 12 !default; -$horizontal_padding: 20px !default; -$vertical_padding: 20px !default; $animation_speed: .3s !default; @mixin vendor($property, $value...){ @@ -35,10 +33,6 @@ $animation_speed: .3s !default; border: 1px dashed lightgray; margin: 0; position: absolute; - top: 0; - left: $horizontal_padding / 2; - right: $horizontal_padding / 2; - bottom: 0; width: auto; z-index: 0 !important; text-align: center; @@ -52,10 +46,6 @@ $animation_speed: .3s !default; > .grid-stack-item-content { margin: 0; position: absolute; - top: 0; - left: $horizontal_padding / 2; - right: $horizontal_padding / 2; - bottom: 0; width: auto; overflow-x: hidden; overflow-y: auto; @@ -95,14 +85,14 @@ $animation_speed: .3s !default; @include vendor(transform, rotate(-45deg)); } - > .ui-resizable-nw { cursor: nw-resize; width: 20px; height: 20px; left: 10px; top: 0; } + > .ui-resizable-nw { cursor: nw-resize; width: 20px; height: 20px; top: 0; } > .ui-resizable-n { cursor: n-resize; height: 10px; top: 0; left: 25px; right: 25px; } - > .ui-resizable-ne { cursor: ne-resize; width: 20px; height: 20px; right: 10px; top: 0; } - > .ui-resizable-e { cursor: e-resize; width: 10px; right: $horizontal_padding / 2; top: 15px; bottom: 15px; } - > .ui-resizable-se { cursor: se-resize; width: 20px; height: 20px; right: 10px; bottom: 0; } + > .ui-resizable-ne { cursor: ne-resize; width: 20px; height: 20px; top: 0; } + > .ui-resizable-e { cursor: e-resize; width: 10px; top: 15px; bottom: 15px; } + > .ui-resizable-se { cursor: se-resize; width: 20px; height: 20px;} > .ui-resizable-s { cursor: s-resize; height: 10px; left: 25px; bottom: 0; right: 25px; } - > .ui-resizable-sw { cursor: sw-resize; width: 20px; height: 20px; left: 10px; bottom: 0; } - > .ui-resizable-w { cursor: w-resize; width: 10px; left: $horizontal_padding / 2; top: 15px; bottom: 15px; } + > .ui-resizable-sw { cursor: sw-resize; width: 20px; height: 20px; bottom: 0; } + > .ui-resizable-w { cursor: w-resize; width: 10px; top: 15px; bottom: 15px; } &.ui-draggable-dragging { &> .ui-resizable-handle { diff --git a/src/gridstack.ts b/src/gridstack.ts index 24a7c7310..aac8b7aa5 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -131,7 +131,7 @@ export class GridStack { private _gsEventHandler = {}; /** @internal */ private _styles: GridCSSStyleSheet; - /** @internal */ + /** @internal flag to keep cells square during resize */ private _isAutoCellHeight: boolean; /** @@ -145,6 +145,7 @@ export class GridStack { obsoleteOpts(opts, 'width', 'column', 'v0.5.3'); obsoleteOpts(opts, 'height', 'maxRow', 'v0.5.3'); + obsoleteOpts(opts, 'verticalMargin', 'margin', 'v2.0'); obsoleteOptsDel(opts, 'oneColumnModeClass', 'v0.6.3', '. Use class `.grid-stack-1` instead'); // container attributes @@ -169,8 +170,8 @@ export class GridStack { placeholderText: '', handle: '.grid-stack-item-content', handleClass: null, - cellHeight: 60, - verticalMargin: 20, + cellHeight: 'auto', + margin: 10, auto: true, minWidth: 768, float: false, @@ -202,13 +203,14 @@ export class GridStack { accept: '.' + (opts.itemClass || 'grid-stack-item') }, removeTimeout: 2000, - verticalMarginUnit: 'px', + marginUnit: 'px', cellHeightUnit: 'px', disableOneColumnMode: false, oneColumnModeDomSort: false }; this.opts = Utils.defaults(opts, defaults); + this.initMargin(); if (this.opts.ddPlugin === false) { this.opts.ddPlugin = GridStackDragDropPlugin; @@ -232,12 +234,13 @@ export class GridStack { this._isAutoCellHeight = (this.opts.cellHeight === 'auto'); if (this._isAutoCellHeight) { - // make the cell square initially - this.cellHeight(Math.round(this.cellWidth()), true); + // make the cell content square initially (will use resize event to keep it square) + let marginDiff = - (this.opts.marginRight as number) - (this.opts.marginLeft as number) + + (this.opts.marginTop as number) + (this.opts.marginBottom as number); + this.cellHeight(this.cellWidth() + marginDiff, false); } else { - this.cellHeight(this.opts.cellHeight, true); + this.cellHeight(this.opts.cellHeight, false); } - this.verticalMargin(this.opts.verticalMargin, true); this.el.classList.add(this.opts._class); @@ -386,12 +389,11 @@ export class GridStack { if (this.opts.cellHeight && this.opts.cellHeight !== 'auto') { return this.opts.cellHeight as number; } - // compute the height taking margin into account (each row has margin other than last one) + // else get first cell height + // or do entire grid and # of rows ? (this.el.getBoundingClientRect().height) / parseInt(this.el.getAttribute('data-gs-current-row')) let el = this.el.querySelector('.' + this.opts.itemClass) as HTMLElement; let height = Utils.toNumber(el.getAttribute('data-gs-height')); - let verticalMargin = this.opts.verticalMargin as number; - - return Math.round((el.offsetHeight - (height - 1) * verticalMargin) / height); + return Math.round(el.offsetHeight / height); } /** @@ -400,20 +402,20 @@ export class GridStack { * Note: You can expect performance issues if call this method too often. * * @param val the cell height - * @param noUpdate (Optional) if true, styles will not be updated + * @param update (Optional) if false, styles will not be updated * * @example * grid.cellHeight(grid.cellWidth() * 1.2); */ - public cellHeight(val: numberOrString, noUpdate?: boolean): GridStack { - let heightData = Utils.parseHeight(val); - if (this.opts.cellHeightUnit === heightData.unit && this.opts.cellHeight === heightData.height) { + public cellHeight(val: numberOrString, update = true): GridStack { + let data = Utils.parseHeight(val); + if (this.opts.cellHeightUnit === data.unit && this.opts.cellHeight === data.height) { return this; } - this.opts.cellHeightUnit = heightData.unit; - this.opts.cellHeight = heightData.height; + this.opts.cellHeightUnit = data.unit; + this.opts.cellHeight = data.height; - if (!noUpdate) { + if (update) { this._updateStyles(); } return this; @@ -423,7 +425,6 @@ export class GridStack { * Gets current cell width. */ public cellWidth(): number { - // TODO: take margin into account (horizontal_padding in .scss) to make cellHeight='auto' square ? (see 810-many-columns.html) return this.el.offsetWidth / this.opts.column; } @@ -977,28 +978,28 @@ export class GridStack { } /** - * Updates the vertical margin - see `GridstackOptions.verticalMargin` for format options. - * + * Updates the margins which will set all 4 sides at once - see `GridstackOptions.margin` for format options. * @param value new vertical margin value - * @param noUpdate (optional) if true, styles will not be updated + * Note: you can instead use `marginTop | marginBottom | marginLeft | marginRight` GridstackOptions to set the sides separately. */ - public verticalMargin(value: numberOrString, noUpdate?: boolean): GridStack { - let heightData = Utils.parseHeight(value); - - if (this.opts.verticalMarginUnit === heightData.unit && this.opts.maxRow === heightData.height) { - return this; + public margin(value: numberOrString): GridStack { + let data = Utils.parseHeight(value); + if (this.opts.marginUnit === data.unit && this.opts.margin === data.height) { + return; } - this.opts.verticalMarginUnit = heightData.unit; - this.opts.verticalMargin = heightData.height; + this.opts.marginUnit = data.unit; + this.opts.marginTop = + this.opts.marginBottom = + this.opts.marginLeft = + this.opts.marginRight = + this.opts.margin = data.height; + this._updateStyles(); - if (!noUpdate) { - this._updateStyles(); - } return this; } /** returns current vertical margin value */ - public getVerticalMargin(): number { return this.opts.verticalMargin as number; } + public getMargin(): number { return this.opts.margin as number; } /** * Returns true if the height of the grid will be less the vertical @@ -1080,19 +1081,14 @@ export class GridStack { return this; } - /** @internal */ + /** @internal updated the CSS styles for row based layout and initial margin setting */ private _updateStyles(maxHeight?: number): GridStack { - if (this._styles === null || this._styles === undefined) { + if (!this._styles) { return this; } - - let prefix = '.' + this.opts._class + ' .' + this.opts.itemClass; - let getHeight; - if (maxHeight === undefined) { maxHeight = this._styles._max; } - this._initStyles(); this._updateContainerHeight(); if (!this.opts.cellHeight) { // The rest will be handled by CSS @@ -1101,49 +1097,39 @@ export class GridStack { if (this._styles._max !== 0 && maxHeight <= this._styles._max) { // Keep it increasing return this; } - let height = this.opts.cellHeight as number; - let margin = this.opts.verticalMargin as number; - - if (!this.opts.verticalMargin || this.opts.cellHeightUnit === this.opts.verticalMarginUnit) { - getHeight = (nbRows: number, nbMargins: number) => { - return (height * nbRows + margin * nbMargins) + this.opts.cellHeightUnit; - } - } else { - getHeight = (nbRows: number, nbMargins: number) => { - if (!nbRows || !nbMargins) { - return (height * nbRows + margin * nbMargins) + this.opts.cellHeightUnit; - } - return 'calc(' + ((height * nbRows) + this.opts.cellHeightUnit) + ' + ' + - ((margin * nbMargins) + this.opts.verticalMarginUnit) + ')'; - } - } + let cellHeight = this.opts.cellHeight as number; + let cellHeightUnit = this.opts.cellHeightUnit; + let prefix = `.${this.opts._class} > .${this.opts.itemClass}`; + // these are done once only if (this._styles._max === 0) { - Utils.insertCSSRule(this._styles, prefix, 'min-height: ' + getHeight(1, 0) + ';', 0); + Utils.addCSSRule(this._styles, prefix, `min-height: ${cellHeight}${cellHeightUnit}`); + // content margins + let top: string = this.opts.marginTop + this.opts.marginUnit; + let bottom: string = this.opts.marginBottom + this.opts.marginUnit; + let right: string = this.opts.marginRight + this.opts.marginUnit; + let left: string = this.opts.marginLeft + this.opts.marginUnit; + let content = `${prefix} > .grid-stack-item-content`; + let placeholder = `.${this.opts._class} > .grid-stack-placeholder > .placeholder-content`; + Utils.addCSSRule(this._styles, content, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`); + Utils.addCSSRule(this._styles, placeholder, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`); + // resize handles offset (to match margin) + Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-ne`, `right: ${right}`); + Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-e`, `right: ${right}`); + Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-se`, `right: ${right}; bottom: ${bottom}`); + Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-nw`, `left: ${left}`); + Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-w`, `left: ${left}`); + Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-sw`, `left: ${left}; bottom: ${bottom}`); } if (maxHeight > this._styles._max) { - for (let i = this._styles._max; i < maxHeight; ++i) { - Utils.insertCSSRule(this._styles, - prefix + '[data-gs-height="' + (i + 1) + '"]', - 'height: ' + getHeight(i + 1, i) + ';', - i - ); - Utils.insertCSSRule(this._styles, - prefix + '[data-gs-min-height="' + (i + 1) + '"]', - 'min-height: ' + getHeight(i + 1, i) + ';', - i - ); - Utils.insertCSSRule(this._styles, - prefix + '[data-gs-max-height="' + (i + 1) + '"]', - 'max-height: ' + getHeight(i + 1, i) + ';', - i - ); - Utils.insertCSSRule(this._styles, - prefix + '[data-gs-y="' + i + '"]', - 'top: ' + getHeight(i, i) + ';', - i - ); + let getHeight = (rows: number): string => (cellHeight * rows) + cellHeightUnit; + for (let i = this._styles._max + 1; i <= maxHeight; i++) { // start at 1 + let height: string = getHeight(i); + Utils.addCSSRule(this._styles, `${prefix}[data-gs-y="${i-1}"]`, `top: ${getHeight(i-1)}`); // start at 0 + Utils.addCSSRule(this._styles, `${prefix}[data-gs-height="${i}"]`, `height: ${height}`); + Utils.addCSSRule(this._styles, `${prefix}[data-gs-min-height="${i}"]`, `min-height: ${height}`); + Utils.addCSSRule(this._styles, `${prefix}[data-gs-max-height="${i}"]`, `max-height: ${height}`); } this._styles._max = maxHeight; } @@ -1154,11 +1140,10 @@ export class GridStack { private _updateContainerHeight(): GridStack { if (this.engine.batchMode) { return this; } let row = this.getRow(); // checks for minRow already - // check for css min height. Each row is cellHeight + verticalMargin, until last one which has no margin below + // check for css min height let cssMinHeight = parseInt(getComputedStyle(this.el)['min-height']); if (cssMinHeight > 0) { - let verticalMargin = this.opts.verticalMargin as number; - let minRow = Math.round((cssMinHeight + verticalMargin) / (this.getCellHeight() + verticalMargin)); + let minRow = Math.round(cssMinHeight / this.getCellHeight()); if (row < minRow) { row = minRow; } @@ -1169,16 +1154,9 @@ export class GridStack { return this; } let cellHeight = this.opts.cellHeight as number; - let vMargin = this.opts.verticalMargin as number; let unit = this.opts.cellHeightUnit; if (!cellHeight) { return this } - - if (unit === this.opts.verticalMarginUnit) { - this.el.style.height = (row * (cellHeight + vMargin) - vMargin) + unit; - } else { - this.el.style.height = 'calc(' + (row * cellHeight) + unit + - ' + ' + (row * (vMargin - 1) + this.opts.verticalMarginUnit) + ')'; - } + this.el.style.height = row * cellHeight + unit; return this; } @@ -1208,7 +1186,7 @@ export class GridStack { private _prepareElementsByNode(el: GridItemHTMLElement, node: GridStackNode): GridStack { // variables used/cashed between the 3 start/move/end methods, in addition to node passed above let cellWidth: number; - let cellFullHeight: number; // internal cellHeight + v-margin + let cellHeight: number; /** called when item starts moving/resizing */ let onStartMoving = (event, ui) => { @@ -1220,9 +1198,7 @@ export class GridStack { this.engine.cleanNodes(); this.engine.beginUpdate(node); cellWidth = this.cellWidth(); - let strictCellHeight = this.getCellHeight(); // heigh without v-margin - // compute height with v-margin (Note: we add 1 margin as last row is missing it) - cellFullHeight = (this.el.getBoundingClientRect().height + this.getVerticalMargin()) / parseInt(this.el.getAttribute('data-gs-current-row')); + cellHeight = this.getCellHeight(); let { target } = event; @@ -1237,11 +1213,10 @@ export class GridStack { node._beforeDragY = node.y; node._prevYPix = ui.position.top; let minHeight = (node.minHeight || 1); - let verticalMargin = this.opts.verticalMargin as number; - // mineHeight - Each row is cellHeight + verticalMargin, until last one which has no margin below + // mineHeight - Each row is cellHeight + margin this.dd.resizable(el, 'option', 'minWidth', cellWidth * (node.minWidth || 1)); - this.dd.resizable(el, 'option', 'minHeight', (strictCellHeight * minHeight) + (minHeight - 1) * verticalMargin); + this.dd.resizable(el, 'option', 'minHeight', cellHeight * minHeight); if (event.type === 'resizestart') { let itemElement = target.querySelector('.grid-stack-item') as HTMLElement; @@ -1256,7 +1231,7 @@ export class GridStack { /** called when item is being dragged/resized */ let dragOrResize = (event: Event, ui) => { let x = Math.round(ui.position.left / cellWidth); - let y = Math.floor((ui.position.top + cellFullHeight / 2) / cellFullHeight); + let y = Math.floor((ui.position.top + cellHeight / 2) / cellHeight); let width; let height; @@ -1296,7 +1271,7 @@ export class GridStack { } else if (event.type === 'resize') { if (x < 0) return; width = Math.round(ui.size.width / cellWidth); - height = Math.round((ui.size.height + this.getVerticalMargin()) / cellFullHeight); + height = Math.round((ui.size.height + this.getMargin()) / cellHeight); } // width and height are undefined if not resizing let _lastTriedWidth = (width || node._lastTriedWidth); @@ -1499,8 +1474,13 @@ export class GridStack { * and remember the prev columns we used. */ private _onResizeHandler(): GridStack { + // make the cells content (minus margin) square again if (this._isAutoCellHeight) { - Utils.throttle(() => { this.cellHeight(Math.round(this.cellWidth()), false)}, 100); + Utils.throttle(() => { + let marginDiff = - (this.opts.marginRight as number) - (this.opts.marginLeft as number) + + (this.opts.marginTop as number) + (this.opts.marginBottom as number); + this.cellHeight(this.cellWidth() + marginDiff); + }, 100); } if (!this.opts.disableOneColumnMode && this.el.clientWidth <= this.opts.minWidth) { @@ -1610,12 +1590,10 @@ export class GridStack { } // if not calculate the grid size based on element outer size - // height: Each row is cellHeight + verticalMargin, until last one which has no margin below let cellWidth = this.cellWidth(); let cellHeight = this.getCellHeight(); - let verticalMargin = this.opts.verticalMargin as number; width = node && node.width ? node.width : Math.ceil(el.offsetWidth / cellWidth); - height = node && node.height ? node.height : Math.round((el.offsetHeight + verticalMargin) / (cellHeight + verticalMargin)); + height = node && node.height ? node.height : Math.round(el.offsetHeight / cellHeight); let newNode = this.engine.prepareNode({width, height, _added: false, _temporary: true}); newNode._isOutOfGrid = true; @@ -1715,6 +1693,48 @@ export class GridStack { return [els]; } + /** @internal initialize margin top/bottom/left/right and units */ + private initMargin(): GridStack { + let data = Utils.parseHeight(this.opts.margin); + this.opts.marginUnit = data.unit; + let margin = this.opts.margin = data.height; + + // see if top/bottom/left/right need to be set as well + if (this.opts.marginTop === undefined) { + this.opts.marginTop = margin; + } else { + data = Utils.parseHeight(this.opts.marginTop); + this.opts.marginTop = data.height; + delete this.opts.margin; + } + + if (this.opts.marginBottom === undefined) { + this.opts.marginBottom = margin; + } else { + data = Utils.parseHeight(this.opts.marginBottom); + this.opts.marginBottom = data.height; + delete this.opts.margin; + } + + if (this.opts.marginRight === undefined) { + this.opts.marginRight = margin; + } else { + data = Utils.parseHeight(this.opts.marginRight); + this.opts.marginRight = data.height; + delete this.opts.margin; + } + + if (this.opts.marginLeft === undefined) { + this.opts.marginLeft = margin; + } else { + data = Utils.parseHeight(this.opts.marginLeft); + this.opts.marginLeft = data.height; + delete this.opts.margin; + } + this.opts.marginUnit = data.unit; // in case side were spelled out, use those units instead... + return this; + } + // legacy method renames /** @internal */ private setGridWidth = obsolete(this, GridStack.prototype.column, 'setGridWidth', 'column', 'v0.5.3'); diff --git a/src/types.ts b/src/types.ts index 0aa4b1fee..b4f42a72b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -91,6 +91,22 @@ export interface GridstackOptions { /** widget class (default?: 'grid-stack-item') */ itemClass?: string; + /** + * gap size between grid item and content (default?: 10). see also marginTop, marginRight,... Can be: + * an integer (px) + * a string (ex: '2em', '20px', '2rem') + */ + margin?: numberOrString; + + /** optional way to specify each individual margin side - default to margin */ + marginTop?: numberOrString; + marginRight?: numberOrString; + marginBottom?: numberOrString; + marginLeft?: numberOrString; + + /** (internal) unit for margin (default? 'px') set when `margin` is set as string with unit (ex: 2rem') */ + marginUnit?: string; + /** maximum rows amount. Default? is 0 which means no maximum rows */ maxRow?: number; @@ -146,16 +162,6 @@ export interface GridstackOptions { */ staticGrid?: boolean; - /** - * vertical gap size (default?: 20). Can be: - * an integer (px) - * a string (ex: '2em', '20px', '2rem') - */ - verticalMargin?: numberOrString; - - /** (internal) unit for verticalMargin (default? 'px') set when `verticalMargin` is set as string with unit (ex: 2rem') */ - verticalMarginUnit?: string; - /** @internal */ _isNested?: boolean; /** @internal */ diff --git a/src/utils.ts b/src/utils.ts index 44898efec..cdcfed996 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -108,11 +108,11 @@ export class Utils { } /** inserts a CSS rule */ - static insertCSSRule(sheet: CSSStyleSheet, selector: string, rules: string, index: number) { - if (typeof sheet.insertRule === 'function') { - sheet.insertRule(selector + '{' + rules + '}', index); - } else if (typeof sheet.addRule === 'function') { - sheet.addRule(selector, rules, index); + static addCSSRule(sheet: CSSStyleSheet, selector: string, rules: string) { + if (typeof sheet.addRule === 'function') { + sheet.addRule(selector, rules); + } else if (typeof sheet.insertRule === 'function') { + sheet.insertRule(`${selector}{${rules}}`); } }