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

Skip to content

Commit 373692a

Browse files
committed
- Removed dynamic stylesheet and migrated to vars
1 parent 4dd3abb commit 373692a

File tree

6 files changed

+95
-113
lines changed

6 files changed

+95
-113
lines changed

doc/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ GridStack will add it to the `<style>` elements it creates.
126126
- `row` - fix grid number of rows. This is a shortcut of writing `minRow:N, maxRow:N`. (default `0` no constrain)
127127
- `rtl` - if `true` turns grid to RTL. Possible values are `true`, `false`, `'auto'` (default: `'auto'`) See [example](https://gridstackjs.com/demo/right-to-left(rtl).html)
128128
- `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 can use the smaller gridstack-static.js lib. A CSS class `grid-stack-static` is also added to the container.
129-
- `styleInHead` - if `true` will add style element to `<head>` otherwise will add it to element's parent node (default `false`).
130129

131130
### Responsive
132131
v10.x supports a much richer responsive behavior, you can have breakpoints of width:column, or auto column sizing, where no code is longer needed.

spec/gridstack-spec.ts

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,41 +1370,24 @@ describe('gridstack', function() {
13701370
afterEach(function() {
13711371
document.body.removeChild(document.getElementById('gs-cont'));
13721372
});
1373-
it('should add STYLE to parent node as a default', function() {
1374-
var options = {
1373+
it('should not add STYLE to parent node', function() {
1374+
const options = {
13751375
cellHeight: 80,
13761376
verticalMargin: 10,
13771377
float: false,
13781378
};
1379-
var grid = GridStack.init(options);
1380-
expect((grid as any)._styles.ownerNode.parentNode.tagName).toBe('DIV'); // any to access private _styles
1379+
GridStack.init(options);
1380+
expect(document.querySelector("style")).toBe(null);
13811381
});
1382-
it('should add STYLE to HEAD if styleInHead === true', function() {
1383-
var options = {
1382+
it('should not add STYLE to HEAD if styleInHead === true', function() {
1383+
const options = {
13841384
cellHeight: 80,
13851385
verticalMargin: 10,
13861386
float: false,
13871387
styleInHead: true
13881388
};
1389-
var grid = GridStack.init(options);
1390-
expect((grid as any)._styles.ownerNode.parentNode.tagName).toBe('HEAD'); // any to access private _styles
1391-
});
1392-
});
1393-
1394-
describe('grid.opts.styleInHead', function() {
1395-
beforeEach(function() {
1396-
document.body.insertAdjacentHTML('afterbegin', gridstackHTML);
1397-
});
1398-
afterEach(function() {
1399-
document.body.removeChild(document.getElementById('gs-cont'));
1400-
});
1401-
it('should add STYLE to parent node as a default', function() {
1402-
var grid = GridStack.init();
1403-
expect((grid as any)._styles.ownerNode.parentNode.tagName).toBe('DIV');
1404-
});
1405-
it('should add STYLE to HEAD if styleInHead === true', function() {
1406-
var grid = GridStack.init({styleInHead: true});
1407-
expect((grid as any)._styles.ownerNode.parentNode.tagName).toBe('HEAD');
1389+
GridStack.init(options);
1390+
expect(document.querySelector("style")).toBe(null);
14081391
});
14091392
});
14101393

src/dd-resizable.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,13 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
206206
/** @internal */
207207
protected _resizeStop(event: MouseEvent): DDResizable {
208208
const ev = Utils.initEvent<MouseEvent>(event, { type: 'resizestop', target: this.el });
209+
// Remove style attr now, so the stop handler can rebuild style attrs
210+
this._cleanHelper();
209211
if (this.option.stop) {
210212
this.option.stop(ev); // Note: ui() not used by gridstack so don't pass
211213
}
212214
this.el.classList.remove('ui-resizable-resizing');
213215
this.triggerEvent('resizestop', ev);
214-
this._cleanHelper();
215216
delete this.startEvent;
216217
delete this.originalRect;
217218
delete this.temporalRect;

src/gridstack.scss

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,48 @@ $animation_speed: .3s !default;
155155
.gs-1 > .grid-stack-item {
156156
width: 100%;
157157
}
158+
159+
.grid-stack > .grid-stack-item {
160+
height: var(--gs-cell-height);
161+
}
162+
163+
.grid-stack > .grid-stack-item > .grid-stack-item-content {
164+
top: var(--gs-item-margin-top);
165+
right: var(--gs-item-margin-right);
166+
bottom: var(--gs-item-margin-bottom);
167+
left: var(--gs-item-margin-left);
168+
}
169+
170+
.grid-stack > .grid-stack-placeholder > .placeholder-content {
171+
top: var(--gs-item-margin-top);
172+
right: var(--gs-item-margin-right);
173+
bottom: var(--gs-item-margin-bottom);
174+
left: var(--gs-item-margin-left);
175+
}
176+
177+
.grid-stack > .grid-stack-item > .ui-resizable-n {
178+
top: var(--gs-item-margin-top);
179+
}
180+
.grid-stack > .grid-stack-item > .ui-resizable-s {
181+
bottom: var(--gs-item-margin-bottom);
182+
}
183+
.grid-stack > .grid-stack-item > .ui-resizable-ne {
184+
right: var(--gs-item-margin-right);
185+
}
186+
.grid-stack > .grid-stack-item > .ui-resizable-e {
187+
right: var(--gs-item-margin-right);
188+
}
189+
.grid-stack > .grid-stack-item > .ui-resizable-se {
190+
right: var(--gs-item-margin-right);
191+
bottom: var(--gs-item-margin-bottom);
192+
}
193+
.grid-stack > .grid-stack-item > .ui-resizable-nw {
194+
left: var(--gs-item-margin-left);
195+
}
196+
.grid-stack > .grid-stack-item > .ui-resizable-w {
197+
left: var(--gs-item-margin-left);
198+
}
199+
.grid-stack > .grid-stack-item > .ui-resizable-sw {
200+
left: var(--gs-item-margin-left);
201+
bottom: var(--gs-item-margin-bottom);
202+
}

src/gridstack.ts

Lines changed: 37 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,6 @@ export interface CellPosition {
4848
y: number;
4949
}
5050

51-
interface GridHTMLStyleElement extends HTMLStyleElement {
52-
_max?: number; // internal tracker of the max # of rows we created
53-
}
54-
5551
// extend with internal fields we need - TODO: move other items in here
5652
interface InternalGridStackOptions extends GridStackOptions {
5753
_alwaysShowResizeHandle?: true | false | 'mobile'; // so we can restore for save
@@ -245,8 +241,6 @@ export class GridStack {
245241
protected _ignoreLayoutsNodeChange: boolean;
246242
/** @internal */
247243
public _gsEventHandler = {};
248-
/** @internal */
249-
protected _styles: GridHTMLStyleElement;
250244
/** @internal flag to keep cells square during resize */
251245
protected _isAutoCellHeight: boolean;
252246
/** @internal limit auto cell resizing method */
@@ -394,8 +388,6 @@ export class GridStack {
394388
float: this.opts.float,
395389
maxRow: this.opts.maxRow,
396390
onChange: (cbNodes) => {
397-
let maxH = 0;
398-
this.engine.nodes.forEach(n => { maxH = Math.max(maxH, n.y + n.h) });
399391
cbNodes.forEach(n => {
400392
let el = n.el;
401393
if (!el) return;
@@ -406,12 +398,12 @@ export class GridStack {
406398
this._writePosAttr(el, n);
407399
}
408400
});
409-
this._updateStyles(false, maxH); // false = don't recreate, just append if need be
401+
this._updateStyles();
410402
}
411403
});
412404

413405
// create initial global styles BEFORE loading children so resizeToContent margin can be calculated correctly
414-
this._updateStyles(false, 0);
406+
this._updateStyles();
415407

416408
if (this.opts.auto) {
417409
this.batchUpdate(); // prevent in between re-layout #1535 TODO: this only set float=true, need to prevent collision check...
@@ -878,7 +870,7 @@ export class GridStack {
878870
this.resizeToContentCheck();
879871

880872
if (update) {
881-
this._updateStyles(true); // true = force re-create for current # of rows
873+
this._updateStyles();
882874
}
883875
return this;
884876
}
@@ -995,7 +987,6 @@ export class GridStack {
995987
} else {
996988
this.el.parentNode.removeChild(this.el);
997989
}
998-
this._removeStylesheet();
999990
if (this.parentGridItem) delete this.parentGridItem.subGrid;
1000991
delete this.parentGridItem;
1001992
delete this.opts;
@@ -1320,7 +1311,7 @@ export class GridStack {
13201311
// restore any sub-grid back
13211312
if (n.subGrid?.el) {
13221313
itemContent.appendChild(n.subGrid.el);
1323-
if (!n.subGrid.opts.styleInHead) n.subGrid._updateStyles(true); // force create
1314+
n.subGrid._updateStyles();
13241315
}
13251316
}
13261317
delete w.content;
@@ -1437,7 +1428,7 @@ export class GridStack {
14371428
this.opts.marginTop = this.opts.marginBottom = this.opts.marginLeft = this.opts.marginRight = undefined;
14381429
this._initMargin();
14391430

1440-
this._updateStyles(true); // true = force re-create
1431+
this._updateStyles();
14411432

14421433
return this;
14431434
}
@@ -1515,78 +1506,30 @@ export class GridStack {
15151506
return this;
15161507
}
15171508

1518-
/** @internal called to delete the current dynamic style sheet used for our layout */
1519-
protected _removeStylesheet(): GridStack {
1520-
1521-
if (this._styles) {
1522-
const styleLocation = this.opts.styleInHead ? undefined : this.el.parentNode as HTMLElement;
1523-
Utils.removeStylesheet(this._styleSheetClass, styleLocation);
1524-
delete this._styles;
1525-
}
1526-
return this;
1509+
private setVar(el: HTMLElement, varName: string, varValue: string) {
1510+
el.style.setProperty(varName, varValue);
15271511
}
15281512

15291513
/** @internal updated/create the CSS styles for row based layout and initial margin setting */
1530-
protected _updateStyles(forceUpdate = false, maxH?: number): GridStack {
1531-
// call to delete existing one if we change cellHeight / margin
1532-
if (forceUpdate) {
1533-
this._removeStylesheet();
1534-
}
1535-
1536-
if (maxH === undefined) maxH = this.getRow();
1514+
protected _updateStyles(): GridStack {
15371515
this._updateContainerHeight();
15381516

15391517
// if user is telling us they will handle the CSS themselves by setting heights to 0. Do we need this opts really ??
15401518
if (this.opts.cellHeight === 0) {
15411519
return this;
15421520
}
15431521

1544-
let cellHeight = this.opts.cellHeight as number;
1545-
let cellHeightUnit = this.opts.cellHeightUnit;
1546-
let prefix = `.${this._styleSheetClass} > .${this.opts.itemClass}`;
1522+
const cellHeight = this.opts.cellHeight as number;
1523+
const cellHeightUnit = this.opts.cellHeightUnit;
1524+
1525+
// these are done once only
1526+
this.setVar(this.el.parentElement, "--gs-cell-height", `${cellHeight}${cellHeightUnit}`);
1527+
// content margins
1528+
this.setVar(this.el.parentElement, "--gs-item-margin-top", `${this.opts.marginTop}${this.opts.marginUnit}`);
1529+
this.setVar(this.el.parentElement, "--gs-item-margin-bottom", `${this.opts.marginBottom}${this.opts.marginUnit}`);
1530+
this.setVar(this.el.parentElement, "--gs-item-margin-right", `${this.opts.marginRight}${this.opts.marginUnit}`);
1531+
this.setVar(this.el.parentElement, "--gs-item-margin-left", `${this.opts.marginLeft}${this.opts.marginUnit}`);
15471532

1548-
// create one as needed
1549-
if (!this._styles) {
1550-
// insert style to parent (instead of 'head' by default) to support WebComponent
1551-
const styleLocation = this.opts.styleInHead ? undefined : this.el.parentNode as HTMLElement;
1552-
this._styles = Utils.createStylesheet(this._styleSheetClass, styleLocation, {
1553-
nonce: this.opts.nonce,
1554-
});
1555-
if (!this._styles) return this;
1556-
this._styles._max = 0;
1557-
1558-
// these are done once only
1559-
Utils.addCSSRule(this._styles, prefix, `height: ${cellHeight}${cellHeightUnit}`);
1560-
// content margins
1561-
let top: string = this.opts.marginTop + this.opts.marginUnit;
1562-
let bottom: string = this.opts.marginBottom + this.opts.marginUnit;
1563-
let right: string = this.opts.marginRight + this.opts.marginUnit;
1564-
let left: string = this.opts.marginLeft + this.opts.marginUnit;
1565-
let content = `${prefix} > .grid-stack-item-content`;
1566-
let placeholder = `.${this._styleSheetClass} > .grid-stack-placeholder > .placeholder-content`;
1567-
Utils.addCSSRule(this._styles, content, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`);
1568-
Utils.addCSSRule(this._styles, placeholder, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`);
1569-
// resize handles offset (to match margin)
1570-
Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-n`, `top: ${top};`);
1571-
Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-s`, `bottom: ${bottom}`);
1572-
Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-ne`, `right: ${right}`);
1573-
Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-e`, `right: ${right}`);
1574-
Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-se`, `right: ${right}; bottom: ${bottom}`);
1575-
Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-nw`, `left: ${left}`);
1576-
Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-w`, `left: ${left}`);
1577-
Utils.addCSSRule(this._styles, `${prefix} > .ui-resizable-sw`, `left: ${left}; bottom: ${bottom}`);
1578-
}
1579-
1580-
// now update the height specific fields
1581-
maxH = maxH || this._styles._max;
1582-
if (maxH > this._styles._max) {
1583-
let getHeight = (rows: number): string => (cellHeight * rows) + cellHeightUnit;
1584-
for (let i = this._styles._max + 1; i <= maxH; i++) { // start at 1
1585-
Utils.addCSSRule(this._styles, `${prefix}[gs-y="${i}"]`, `top: ${getHeight(i)}`);
1586-
Utils.addCSSRule(this._styles, `${prefix}[gs-h="${i+1}"]`, `height: ${getHeight(i+1)}`); // start at 2
1587-
}
1588-
this._styles._max = maxH;
1589-
}
15901533
return this;
15911534
}
15921535

@@ -1645,17 +1588,27 @@ export class GridStack {
16451588
return this;
16461589
}
16471590

1648-
/** @internal call to write position x,y,w,h attributes back to element */
1649-
protected _writePosAttr(el: HTMLElement, n: GridStackPosition): GridStack {
1650-
if (n.x !== undefined && n.x !== null) { el.setAttribute('gs-x', String(n.x)); }
1651-
if (n.y !== undefined && n.y !== null) { el.setAttribute('gs-y', String(n.y)); }
1652-
n.w > 1 ? el.setAttribute('gs-w', String(n.w)) : el.removeAttribute('gs-w');
1653-
n.h > 1 ? el.setAttribute('gs-h', String(n.h)) : el.removeAttribute('gs-h');
1591+
/**
1592+
* Call to write position x,y,w,h attributes back to element
1593+
* In addition, updates the inline top/height inline style as well
1594+
* @internal
1595+
*/
1596+
protected _writePosAttr(el: HTMLElement, node: GridStackNode): GridStack {
1597+
if (node.x !== undefined && node.x !== null) { el.setAttribute('gs-x', String(node.x)); }
1598+
if (node.y !== undefined && node.y !== null) { el.setAttribute('gs-y', String(node.y)); }
1599+
node.w > 1 ? el.setAttribute('gs-w', String(node.w)) : el.removeAttribute('gs-w');
1600+
node.h > 1 ? el.setAttribute('gs-h', String(node.h)) : el.removeAttribute('gs-h');
1601+
// Avoid overwriting the inline style of the draggable element, but update the placeholder
1602+
if (!node._moving || this._placeholder === el) {
1603+
// Set inline style, refer CSS variables
1604+
el.style.top = `calc(${node.y} * var(--gs-cell-height))`;
1605+
el.style.height = `calc(${node.h} * var(--gs-cell-height))`;
1606+
}
16541607
return this;
16551608
}
16561609

16571610
/** @internal call to write any default attributes back to element */
1658-
protected _writeAttr(el: HTMLElement, node: GridStackWidget): GridStack {
1611+
protected _writeAttr(el: HTMLElement, node: GridStackNode): GridStack {
16591612
if (!node) return this;
16601613
this._writePosAttr(el, node);
16611614

@@ -2243,7 +2196,7 @@ export class GridStack {
22432196
this._prepareElement(el, true, node);
22442197
if (subGrid) {
22452198
subGrid.parentGridItem = node;
2246-
if (!subGrid.opts.styleInHead) subGrid._updateStyles(true); // re-create sub-grid styles now that we've moved
2199+
subGrid._updateStyles(); // re-create sub-grid styles now that we've moved
22472200
}
22482201
this._updateContainerHeight();
22492202
this.engine.addedNodes.push(node);// @ts-ignore
@@ -2406,7 +2359,7 @@ export class GridStack {
24062359
node.el = this.placeholder;
24072360
node._lastUiPosition = ui.position;
24082361
node._prevYPix = ui.position.top;
2409-
node._moving = (event.type === 'dragstart'); // 'dropover' are not initially moving so they can go exactly where they enter (will push stuff out of the way)
2362+
node._moving = (event.type === 'dragstart' || event.type === 'resizestart'); // 'dropover' are not initially moving so they can go exactly where they enter (will push stuff out of the way)
24102363
delete node._lastTried;
24112364

24122365
if (event.type === 'dropover' && node._temporaryRemoved) {

src/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export const gridDefaults: GridStackOptions = {
3535
// handleClass: null,
3636
// removable: false,
3737
// staticGrid: false,
38-
// styleInHead: false,
3938
//removable
4039
};
4140

@@ -265,7 +264,9 @@ export interface GridStackOptions {
265264
*/
266265
staticGrid?: boolean;
267266

268-
/** if `true` will add style element to `<head>` otherwise will add it to element's parent node (default `false`). */
267+
/**
268+
* @deprecated Not used anymore, styles are now implemented with local CSS variables
269+
*/
269270
styleInHead?: boolean;
270271

271272
/** list of differences in options for automatically created sub-grids under us (inside our grid-items) */

0 commit comments

Comments
 (0)