Thanks to visit codestin.com
Credit goes to github.com

Skip to content

setting margin option support CSS '5px 10px 0 20px' format #1443

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Change log
- add `data-gs-static-grid` attribute
- fix getting DOM element by id with number works (api that uses `GridStackElement` handle more string formats)
- fix setting `marginTop` (or any 4 sides) to cause resize to break. Thanks [@deadivan](https://github.com/deadivan) for suggested fix.
- add `margin` support multi CSS format `'5px 10px 0 20px'` or `'5em 10em'`

## 2.1.0 (2020-10-28)

Expand Down
10 changes: 6 additions & 4 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ Return list of GridItem HTML dom elements (excluding temporary placeholder)

### getMargin()

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

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

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

### margin(value: numberOrString)

set the top/right/bottom/left margin between grid item and content. Parameters:
- `value` - new margin value. see `cellHeight` for possible value formats.
Note: you can instead use `marginTop | marginBottom | marginLeft | marginRight` so set the sides separately.
gap between grid item and content (default?: 10). This will set all 4 sides and support the CSS formats below
- an `integer` (px)
- a string with possible units (ex: `'5'`, `'2em'`, `'20px'`, `'2rem'`)
- 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).
- Note: all sides must have same units (last one wins, default px)

### maxHeight(el, val)

Expand Down
42 changes: 41 additions & 1 deletion spec/gridstack-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ describe('gridstack', function() {
let grid: any = GridStack.init(options);
expect(grid.getMargin()).toBe(5);
spyOn(grid, '_updateStyles');
grid.margin('5px', false);
grid.margin('5px');
expect(grid._updateStyles).not.toHaveBeenCalled();
expect(grid.getMargin()).toBe(5);
});
Expand Down Expand Up @@ -1237,6 +1237,46 @@ describe('gridstack', function() {
expect(grid.opts.marginLeft).toBe(5);
expect(grid.opts.marginRight).toBe(5);
});
it('init 2 values', function() {
let options = {
cellHeight: 80,
margin: '5px 10'
};
let grid: any = GridStack.init(options);
expect(grid.getMargin()).toBe(undefined);
expect(grid.opts.marginTop).toBe(5);
expect(grid.opts.marginBottom).toBe(5);
expect(grid.opts.marginLeft).toBe(10);
expect(grid.opts.marginRight).toBe(10);
});
it('init 4 values', function() {
let options = {
cellHeight: 80,
margin: '1 2 0em 3'
};
let grid: any = GridStack.init(options);
expect(grid.getMargin()).toBe(undefined);
expect(grid.opts.marginTop).toBe(1);
expect(grid.opts.marginRight).toBe(2);
expect(grid.opts.marginBottom).toBe(0);
expect(grid.opts.marginLeft).toBe(3);
});
it('set 2 values, should update style', function() {
let options = {
cellHeight: 80,
margin: 5
};
let grid = GridStack.init(options);
expect(grid.getMargin()).toBe(5);
spyOn(grid as any, '_updateStyles');
grid.margin('1px 0');
expect((grid as any)._updateStyles).toHaveBeenCalled();
expect(grid.getMargin()).toBe(undefined);
expect(grid.opts.marginTop).toBe(1);
expect(grid.opts.marginBottom).toBe(1);
expect(grid.opts.marginLeft).toBe(0);
expect(grid.opts.marginRight).toBe(0);
});
});

describe('grid.opts.rtl', function() {
Expand Down
55 changes: 37 additions & 18 deletions src/gridstack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

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

Expand Down Expand Up @@ -1021,27 +1021,27 @@ export class GridStack {
}

/**
* Updates the margins which will set all 4 sides at once - see `GridStackOptions.margin` for format options.
* @param value new vertical margin value
* Note: you can instead use `marginTop | marginBottom | marginLeft | marginRight` GridStackOptions to set the sides separately.
* 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).
* @param value margin value
*/
public margin(value: numberOrString): GridStack {
let data = Utils.parseHeight(value);
if (this.opts.marginUnit === data.unit && this.opts.margin === data.height) {
return;
}
this.opts.marginUnit = data.unit;
this.opts.marginTop =
this.opts.marginBottom =
this.opts.marginLeft =
this.opts.marginRight =
this.opts.margin = data.height;
let isMultiValue = (typeof value === 'string' && value.split(' ').length > 1);
// check if we can skip re-creating our CSS file... won't check if multi values (too much hassle)
if (!isMultiValue) {
let data = Utils.parseHeight(value);
if (this.opts.marginUnit === data.unit && this.opts.margin === data.height) return;
}
// re-use existing margin handling
this.opts.margin = value;
this.opts.marginTop = this.opts.marginBottom = this.opts.marginLeft = this.opts.marginRight = undefined;
this.initMargin();

this._updateStyles(true); // true = force re-create

return this;
}

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

/**
Expand Down Expand Up @@ -1818,9 +1818,28 @@ export class GridStack {

/** @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;

let data: HeightData;
let margin = 0;

// support passing multiple values like CSS (ex: '5px 10px 0 20px')
let margins: string[] = [];
if (typeof this.opts.margin === 'string') {
margins = this.opts.margin.split(' ')
}
if (margins.length === 2) { // top/bot, left/right like CSS
this.opts.marginTop = this.opts.marginBottom = margins[0];
this.opts.marginLeft = this.opts.marginRight = margins[1];
} else if (margins.length === 4) { // Clockwise like CSS
this.opts.marginTop = margins[0];
this.opts.marginRight = margins[1];
this.opts.marginBottom = margins[2];
this.opts.marginLeft = margins[3];
} else {
data = Utils.parseHeight(this.opts.margin);
this.opts.marginUnit = data.unit;
margin = this.opts.margin = data.height;
}

// see if top/bottom/left/right need to be set as well
if (this.opts.marginTop === undefined) {
Expand Down
8 changes: 5 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,15 @@ export interface GridStackOptions {
itemClass?: string;

/**
* gap size between grid item and content (default?: 10). see also marginTop, marginRight,... Can be:
* gap between grid item and content (default?: 10). This will set all 4 sides and support the CSS formats below
* an integer (px)
* a string (ex: '2em', '20px', '2rem')
* a string with possible units (ex: '2em', '20px', '2rem')
* 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).
* Note: all sides must have same units (last one wins, default px)
*/
margin?: numberOrString;

/** optional way to specify each individual margin side - default to margin */
/** OLD way to optionally set each side - use margin: '5px 10px 0 20px' instead. Used internally to store each side. */
marginTop?: numberOrString;
marginRight?: numberOrString;
marginBottom?: numberOrString;
Expand Down
6 changes: 3 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,18 @@ export class Utils {

static parseHeight(val: numberOrString): HeightData {
let height: number;
let heightUnit = 'px';
let unit = 'px';
if (typeof val === 'string') {
let match = val.match(/^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw|%)?$/);
if (!match) {
throw new Error('Invalid height');
}
heightUnit = match[2] || 'px';
unit = match[2] || 'px';
height = parseFloat(match[1]);
} else {
height = val;
}
return { height, unit: heightUnit }
return { height, unit };
}

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