diff --git a/projects/angular-gridster2/src/lib/gridsterItem.ts b/projects/angular-gridster2/src/lib/gridsterItem.ts index 94611400..be80279f 100644 --- a/projects/angular-gridster2/src/lib/gridsterItem.ts +++ b/projects/angular-gridster2/src/lib/gridsterItem.ts @@ -20,6 +20,7 @@ import { import { Gridster } from './gridster'; import { GridsterDraggable } from './gridsterDraggable'; import type { GridsterItemConfig, ResizableHandles } from './gridsterItemConfig'; +import { getItemHeightMargin, getItemWidthMargin } from './gridsterMargin'; import { GridsterResizable } from './gridsterResizable'; import { GridsterUtils } from './gridsterUtils'; @@ -130,8 +131,8 @@ export class GridsterItem implements OnInit, OnDestroy { const $item = this.$item(); const top = $item.y * this.gridster.curRowHeight; const left = $item.x * this.gridster.curColWidth; - const width = $item.cols * this.gridster.curColWidth - $options.margin; - const height = $item.rows * this.gridster.curRowHeight - $options.margin; + const width = $item.cols * this.gridster.curColWidth - getItemWidthMargin($options); + const height = $item.rows * this.gridster.curRowHeight - getItemHeightMargin($options); this.top = top; this.left = left; diff --git a/projects/angular-gridster2/src/lib/gridsterMargin.ts b/projects/angular-gridster2/src/lib/gridsterMargin.ts new file mode 100644 index 00000000..0c2fec7b --- /dev/null +++ b/projects/angular-gridster2/src/lib/gridsterMargin.ts @@ -0,0 +1,19 @@ +import { GridType, type GridsterConfigStrict } from './gridsterConfig'; + +type GridsterMarginOptions = Pick; + +export function getItemWidthMargin($options: GridsterMarginOptions): number { + if ($options.ignoreMarginInRow && ($options.gridType === GridType.Fixed || $options.gridType === GridType.HorizontalFixed)) { + return 0; + } + + return $options.margin; +} + +export function getItemHeightMargin($options: GridsterMarginOptions): number { + if ($options.ignoreMarginInRow && ($options.gridType === GridType.Fixed || $options.gridType === GridType.VerticalFixed)) { + return 0; + } + + return $options.margin; +} diff --git a/projects/angular-gridster2/src/lib/gridsterRenderer.ts b/projects/angular-gridster2/src/lib/gridsterRenderer.ts index bfcd246d..dc38b0e6 100644 --- a/projects/angular-gridster2/src/lib/gridsterRenderer.ts +++ b/projects/angular-gridster2/src/lib/gridsterRenderer.ts @@ -3,6 +3,7 @@ import { Renderer2 } from '@angular/core'; import { Gridster } from './gridster'; import { DirTypes, GridType } from './gridsterConfig'; import { GridsterItemConfig } from './gridsterItemConfig'; +import { getItemHeightMargin, getItemWidthMargin } from './gridsterMargin'; import { CommonGridStyle, GridColumnCachedStyle, GridRowCachedStyle } from './gridsterRendererTypes'; export class GridsterRenderer { @@ -40,8 +41,8 @@ export class GridsterRenderer { } else { const x = Math.round(this.gridster.curColWidth * item.x); const y = Math.round(this.gridster.curRowHeight * item.y); - const width = this.gridster.curColWidth * item.cols - $options.margin; - const height = this.gridster.curRowHeight * item.rows - $options.margin; + const width = this.gridster.curColWidth * item.cols - getItemWidthMargin($options); + const height = this.gridster.curRowHeight * item.rows - getItemHeightMargin($options); // set the cell style this.setCellPosition(renderer, el, x, y); renderer.setStyle(el, 'width', width + 'px'); @@ -127,12 +128,14 @@ export class GridsterRenderer { } getGridColumnStyle(i: number): CommonGridStyle { - const margin = this.gridster.$options().margin; + const $options = this.gridster.$options(); + const widthMargin = getItemWidthMargin($options); + const heightMargin = getItemHeightMargin($options); // generates the new style const newPos: GridColumnCachedStyle = { left: this.gridster.curColWidth * i, - width: this.gridster.curColWidth - margin, - height: this.gridster.gridRows.length * this.gridster.curRowHeight - margin, + width: this.gridster.curColWidth - widthMargin, + height: this.gridster.gridRows.length * this.gridster.curRowHeight - heightMargin, style: {} }; newPos.style = { @@ -153,12 +156,14 @@ export class GridsterRenderer { } getGridRowStyle(i: number): CommonGridStyle { - const margin = this.gridster.$options().margin; + const $options = this.gridster.$options(); + const widthMargin = getItemWidthMargin($options); + const heightMargin = getItemHeightMargin($options); // generates the new style const newPos: GridRowCachedStyle = { top: this.gridster.curRowHeight * i, - width: this.gridster.gridColumns.length * this.gridster.curColWidth + margin, - height: this.gridster.curRowHeight - margin, + width: this.gridster.gridColumns.length * this.gridster.curColWidth + widthMargin, + height: this.gridster.curRowHeight - heightMargin, style: {} }; newPos.style = { diff --git a/projects/angular-gridster2/src/lib/tests/gridsterRenderer.spec.ts b/projects/angular-gridster2/src/lib/tests/gridsterRenderer.spec.ts new file mode 100644 index 00000000..8e172367 --- /dev/null +++ b/projects/angular-gridster2/src/lib/tests/gridsterRenderer.spec.ts @@ -0,0 +1,98 @@ +import { Renderer2 } from '@angular/core'; + +import { Gridster } from '../gridster'; +import { DirTypes, GridType } from '../gridsterConfig'; +import { GridsterItem } from '../gridsterItem'; +import { GridsterItemConfig } from '../gridsterItemConfig'; +import { GridsterRenderer } from '../gridsterRenderer'; + +describe('GridsterRenderer', () => { + const item: GridsterItemConfig = { cols: 13, rows: 6, y: 0, x: 0 }; + + function makeGridster() { + const options = { + gridType: GridType.VerticalFixed, + margin: 20, + outerMargin: true, + outerMarginTop: null, + outerMarginRight: null, + outerMarginBottom: null, + outerMarginLeft: null, + fixedColWidth: 20, + fixedRowHeight: 20, + keepFixedHeightInMobile: true, + keepFixedWidthInMobile: false, + ignoreMarginInRow: true, + useTransformPositioning: false, + dirType: DirTypes.LTR + }; + + return { + $options: () => options, + options: () => ({}), + mobile: false, + curColWidth: 50, + curRowHeight: 20, + curWidth: 1000, + rows: 20, + columns: 20, + gridRows: new Array(20), + gridColumns: new Array(20) + } as unknown as Gridster; + } + + it('does not subtract row margin from item height when ignoreMarginInRow is true', () => { + const gridster = makeGridster(); + const renderer = new GridsterRenderer(gridster); + const styles: Record = {}; + const angularRenderer = { + setStyle: (_el: Element, style: string, value: string | null) => { + styles[style] = value; + } + } as Renderer2; + + renderer.updateItem(document.createElement('div'), item, angularRenderer); + + expect(styles.height).toBe('120px'); + expect(styles.width).toBe('630px'); + }); + + it('uses the same row margin calculation for display grid rows', () => { + const gridster = makeGridster(); + const renderer = new GridsterRenderer(gridster); + + expect(renderer.getGridRowStyle(0).height).toBe('20px'); + expect(renderer.getGridColumnStyle(0).height).toBe('400px'); + }); +}); + +describe('GridsterItem', () => { + it('keeps cached item height in sync with renderer sizing when ignoreMarginInRow is true', () => { + const gridster = { + options: () => ({}), + $options: () => ({ + gridType: GridType.VerticalFixed, + margin: 20, + ignoreMarginInRow: true, + scrollToNewItems: false + }), + curColWidth: 50, + curRowHeight: 20 + } as unknown as Gridster; + + const itemComponent = { + gridster, + $item: () => ({ cols: 13, rows: 6, y: 0, x: 0 }), + item: () => ({}), + init: true, + width: 0, + height: 0, + itemResize: { emit: () => undefined } + } as unknown as GridsterItem; + + GridsterItem.prototype.updateItemSize.call(itemComponent); + + expect(itemComponent.height).toBe(120); + expect(itemComponent.width).toBe(630); + }); +});