Skip to content

Commit bcd6093

Browse files
author
Alain Dumesny
authored
Merge pull request #1443 from adumesny/develop
setting margin option support CSS '5px 10px 0 20px' format
2 parents 32bbc95 + b1eb1da commit bcd6093

File tree

6 files changed

+93
-29
lines changed

6 files changed

+93
-29
lines changed

doc/CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Change log
4646
- add `data-gs-static-grid` attribute
4747
- fix getting DOM element by id with number works (api that uses `GridStackElement` handle more string formats)
4848
- fix setting `marginTop` (or any 4 sides) to cause resize to break. Thanks [@deadivan](https://github.com/deadivan) for suggested fix.
49+
- add `margin` support multi CSS format `'5px 10px 0 20px'` or `'5em 10em'`
4950

5051
## 2.1.0 (2020-10-28)
5152

doc/README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ Return list of GridItem HTML dom elements (excluding temporary placeholder)
384384

385385
### getMargin()
386386

387-
returns current margin value.
387+
returns current margin value (undefined if all 4 sides don't match).
388388

389389
### isAreaEmpty(x, y, width, height)
390390

@@ -423,9 +423,11 @@ grid.makeWidget('#gsi-1');
423423

424424
### margin(value: numberOrString)
425425

426-
set the top/right/bottom/left margin between grid item and content. Parameters:
427-
- `value` - new margin value. see `cellHeight` for possible value formats.
428-
Note: you can instead use `marginTop | marginBottom | marginLeft | marginRight` so set the sides separately.
426+
gap between grid item and content (default?: 10). This will set all 4 sides and support the CSS formats below
427+
- an `integer` (px)
428+
- a string with possible units (ex: `'5'`, `'2em'`, `'20px'`, `'2rem'`)
429+
- string with space separated values (ex: `'5px 10px 0 20px'` for all 4 sides, or `'5em 10em'` for top/bottom and left/right pairs like CSS).
430+
- Note: all sides must have same units (last one wins, default px)
429431

430432
### maxHeight(el, val)
431433

spec/gridstack-spec.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@ describe('gridstack', function() {
12041204
let grid: any = GridStack.init(options);
12051205
expect(grid.getMargin()).toBe(5);
12061206
spyOn(grid, '_updateStyles');
1207-
grid.margin('5px', false);
1207+
grid.margin('5px');
12081208
expect(grid._updateStyles).not.toHaveBeenCalled();
12091209
expect(grid.getMargin()).toBe(5);
12101210
});
@@ -1237,6 +1237,46 @@ describe('gridstack', function() {
12371237
expect(grid.opts.marginLeft).toBe(5);
12381238
expect(grid.opts.marginRight).toBe(5);
12391239
});
1240+
it('init 2 values', function() {
1241+
let options = {
1242+
cellHeight: 80,
1243+
margin: '5px 10'
1244+
};
1245+
let grid: any = GridStack.init(options);
1246+
expect(grid.getMargin()).toBe(undefined);
1247+
expect(grid.opts.marginTop).toBe(5);
1248+
expect(grid.opts.marginBottom).toBe(5);
1249+
expect(grid.opts.marginLeft).toBe(10);
1250+
expect(grid.opts.marginRight).toBe(10);
1251+
});
1252+
it('init 4 values', function() {
1253+
let options = {
1254+
cellHeight: 80,
1255+
margin: '1 2 0em 3'
1256+
};
1257+
let grid: any = GridStack.init(options);
1258+
expect(grid.getMargin()).toBe(undefined);
1259+
expect(grid.opts.marginTop).toBe(1);
1260+
expect(grid.opts.marginRight).toBe(2);
1261+
expect(grid.opts.marginBottom).toBe(0);
1262+
expect(grid.opts.marginLeft).toBe(3);
1263+
});
1264+
it('set 2 values, should update style', function() {
1265+
let options = {
1266+
cellHeight: 80,
1267+
margin: 5
1268+
};
1269+
let grid = GridStack.init(options);
1270+
expect(grid.getMargin()).toBe(5);
1271+
spyOn(grid as any, '_updateStyles');
1272+
grid.margin('1px 0');
1273+
expect((grid as any)._updateStyles).toHaveBeenCalled();
1274+
expect(grid.getMargin()).toBe(undefined);
1275+
expect(grid.opts.marginTop).toBe(1);
1276+
expect(grid.opts.marginBottom).toBe(1);
1277+
expect(grid.opts.marginLeft).toBe(0);
1278+
expect(grid.opts.marginRight).toBe(0);
1279+
});
12401280
});
12411281

12421282
describe('grid.opts.rtl', function() {

src/gridstack.ts

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import { GridStackEngine } from './gridstack-engine';
10-
import { obsoleteOpts, obsoleteOptsDel, obsoleteAttr, obsolete, Utils } from './utils';
10+
import { obsoleteOpts, obsoleteOptsDel, obsoleteAttr, obsolete, Utils, HeightData } from './utils';
1111
import { GridItemHTMLElement, GridStackWidget, GridStackNode, GridStackOptions, numberOrString, ColumnOptions } from './types';
1212
import { GridStackDD } from './gridstack-dd';
1313

@@ -1021,27 +1021,27 @@ export class GridStack {
10211021
}
10221022

10231023
/**
1024-
* Updates the margins which will set all 4 sides at once - see `GridStackOptions.margin` for format options.
1025-
* @param value new vertical margin value
1026-
* Note: you can instead use `marginTop | marginBottom | marginLeft | marginRight` GridStackOptions to set the sides separately.
1024+
* Updates the margins which will set all 4 sides at once - see `GridStackOptions.margin` for format options (CSS string format of 1,2,4 values or single number).
1025+
* @param value margin value
10271026
*/
10281027
public margin(value: numberOrString): GridStack {
1029-
let data = Utils.parseHeight(value);
1030-
if (this.opts.marginUnit === data.unit && this.opts.margin === data.height) {
1031-
return;
1032-
}
1033-
this.opts.marginUnit = data.unit;
1034-
this.opts.marginTop =
1035-
this.opts.marginBottom =
1036-
this.opts.marginLeft =
1037-
this.opts.marginRight =
1038-
this.opts.margin = data.height;
1028+
let isMultiValue = (typeof value === 'string' && value.split(' ').length > 1);
1029+
// check if we can skip re-creating our CSS file... won't check if multi values (too much hassle)
1030+
if (!isMultiValue) {
1031+
let data = Utils.parseHeight(value);
1032+
if (this.opts.marginUnit === data.unit && this.opts.margin === data.height) return;
1033+
}
1034+
// re-use existing margin handling
1035+
this.opts.margin = value;
1036+
this.opts.marginTop = this.opts.marginBottom = this.opts.marginLeft = this.opts.marginRight = undefined;
1037+
this.initMargin();
1038+
10391039
this._updateStyles(true); // true = force re-create
10401040

10411041
return this;
10421042
}
10431043

1044-
/** returns current margin value (undefined if all 4 sides don't match) */
1044+
/** returns current margin number value (undefined if 4 sides don't match) */
10451045
public getMargin(): number { return this.opts.margin as number; }
10461046

10471047
/**
@@ -1818,9 +1818,28 @@ export class GridStack {
18181818

18191819
/** @internal initialize margin top/bottom/left/right and units */
18201820
private initMargin(): GridStack {
1821-
let data = Utils.parseHeight(this.opts.margin);
1822-
this.opts.marginUnit = data.unit;
1823-
let margin = this.opts.margin = data.height;
1821+
1822+
let data: HeightData;
1823+
let margin = 0;
1824+
1825+
// support passing multiple values like CSS (ex: '5px 10px 0 20px')
1826+
let margins: string[] = [];
1827+
if (typeof this.opts.margin === 'string') {
1828+
margins = this.opts.margin.split(' ')
1829+
}
1830+
if (margins.length === 2) { // top/bot, left/right like CSS
1831+
this.opts.marginTop = this.opts.marginBottom = margins[0];
1832+
this.opts.marginLeft = this.opts.marginRight = margins[1];
1833+
} else if (margins.length === 4) { // Clockwise like CSS
1834+
this.opts.marginTop = margins[0];
1835+
this.opts.marginRight = margins[1];
1836+
this.opts.marginBottom = margins[2];
1837+
this.opts.marginLeft = margins[3];
1838+
} else {
1839+
data = Utils.parseHeight(this.opts.margin);
1840+
this.opts.marginUnit = data.unit;
1841+
margin = this.opts.margin = data.height;
1842+
}
18241843

18251844
// see if top/bottom/left/right need to be set as well
18261845
if (this.opts.marginTop === undefined) {

src/types.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,15 @@ export interface GridStackOptions {
100100
itemClass?: string;
101101

102102
/**
103-
* gap size between grid item and content (default?: 10). see also marginTop, marginRight,... Can be:
103+
* gap between grid item and content (default?: 10). This will set all 4 sides and support the CSS formats below
104104
* an integer (px)
105-
* a string (ex: '2em', '20px', '2rem')
105+
* a string with possible units (ex: '2em', '20px', '2rem')
106+
* string with space separated values (ex: '5px 10px 0 20px' for all 4 sides, or '5em 10em' for top/bottom and left/right pairs like CSS).
107+
* Note: all sides must have same units (last one wins, default px)
106108
*/
107109
margin?: numberOrString;
108110

109-
/** optional way to specify each individual margin side - default to margin */
111+
/** OLD way to optionally set each side - use margin: '5px 10px 0 20px' instead. Used internally to store each side. */
110112
marginTop?: numberOrString;
111113
marginRight?: numberOrString;
112114
marginBottom?: numberOrString;

src/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,18 @@ export class Utils {
140140

141141
static parseHeight(val: numberOrString): HeightData {
142142
let height: number;
143-
let heightUnit = 'px';
143+
let unit = 'px';
144144
if (typeof val === 'string') {
145145
let match = val.match(/^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw|%)?$/);
146146
if (!match) {
147147
throw new Error('Invalid height');
148148
}
149-
heightUnit = match[2] || 'px';
149+
unit = match[2] || 'px';
150150
height = parseFloat(match[1]);
151151
} else {
152152
height = val;
153153
}
154-
return { height, unit: heightUnit }
154+
return { height, unit };
155155
}
156156

157157
/** copies unset fields in target to use the given default sources values */

0 commit comments

Comments
 (0)