diff --git a/examples/webpack-demo-vanilla-bundle/package.json b/examples/webpack-demo-vanilla-bundle/package.json
index 1dfe0908f..bc659cce1 100644
--- a/examples/webpack-demo-vanilla-bundle/package.json
+++ b/examples/webpack-demo-vanilla-bundle/package.json
@@ -36,7 +36,7 @@
"@types/jquery": "^3.5.4",
"@types/moment": "^2.13.0",
"@types/node": "^14.14.7",
- "@types/webpack": "^4.41.24",
+ "@types/webpack": "^4.41.25",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^6.3.0",
"css-loader": "^5.0.1",
@@ -44,7 +44,7 @@
"fork-ts-checker-webpack-plugin": "^6.0.1",
"html-loader": "^1.3.2",
"html-webpack-plugin": "^4.5.0",
- "mini-css-extract-plugin": "^1.3.0",
+ "mini-css-extract-plugin": "^1.3.1",
"node-sass": "5.0.0",
"sass-loader": "^10.0.5",
"style-loader": "^2.0.0",
diff --git a/examples/webpack-demo-vanilla-bundle/src/examples/example12.ts b/examples/webpack-demo-vanilla-bundle/src/examples/example12.ts
index a826c326b..035ddfcd7 100644
--- a/examples/webpack-demo-vanilla-bundle/src/examples/example12.ts
+++ b/examples/webpack-demo-vanilla-bundle/src/examples/example12.ts
@@ -124,7 +124,7 @@ export class Example12 {
initializeGrid() {
this.columnDefinitions = [
{
- id: 'title', name: 'Title', field: 'title', sortable: true, type: FieldType.string,
+ id: 'title', name: 'Title', field: 'title', sortable: true, type: FieldType.string, minWidth: 100,
filterable: true, columnGroup: 'Common Factor',
filter: { model: Filters.compoundInputText },
formatter: Formatters.multiple, params: { formatters: [Formatters.uppercase, Formatters.bold] },
@@ -142,13 +142,13 @@ export class Example12 {
editor: { model: Editors.float, massUpdate: true, decimal: 2, valueStep: 1, minValue: 0, maxValue: 10000, alwaysSaveOnEnterKey: true, required: true },
},
{
- id: 'cost', name: 'Cost', field: 'cost', width: 90,
+ id: 'cost', name: 'Cost', field: 'cost', width: 90, minWidth: 100,
sortable: true, filterable: true, type: FieldType.number, columnGroup: 'Analysis',
filter: { model: Filters.compoundInputNumber },
formatter: Formatters.dollar,
},
{
- id: 'percentComplete', name: '% Complete', field: 'percentComplete',
+ id: 'percentComplete', name: '% Complete', field: 'percentComplete', minWidth: 100,
type: FieldType.number,
sortable: true, filterable: true, columnGroup: 'Analysis',
filter: { model: Filters.compoundSlider, operator: '>=' },
@@ -170,7 +170,7 @@ export class Example12 {
},
},
{
- id: 'start', name: 'Start', field: 'start', sortable: true,
+ id: 'start', name: 'Start', field: 'start', sortable: true, minWidth: 100,
formatter: Formatters.dateUs, columnGroup: 'Period',
type: FieldType.dateIso, outputType: FieldType.dateUs,
filterable: true, filter: { model: Filters.compoundDate },
@@ -190,7 +190,7 @@ export class Example12 {
// editor: { model: Editors.singleSelect, collection: [{ value: true, label: 'Yes' }, { value: false, label: 'No' }], },
},
{
- id: 'finish', name: 'Finish', field: 'finish', sortable: true,
+ id: 'finish', name: 'Finish', field: 'finish', sortable: true, minWidth: 100,
formatter: Formatters.dateUs, columnGroup: 'Period',
type: FieldType.dateIso, outputType: FieldType.dateUs,
filterable: true, filter: { model: Filters.compoundDate },
@@ -278,7 +278,7 @@ export class Example12 {
}
},
{
- id: 'action', name: 'Action', field: 'action', width: 70, maxWidth: 70,
+ id: 'action', name: 'Action', field: 'action', width: 70, minWidth: 70, maxWidth: 70,
excludeFromExport: true,
formatter: () => `
`,
cellMenu: {
diff --git a/packages/common/package.json b/packages/common/package.json
index 2517188d6..e44938fe0 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -80,11 +80,11 @@
"autoprefixer": "^10.0.1",
"copyfiles": "^2.4.0",
"cross-env": "^7.0.2",
- "mini-css-extract-plugin": "^1.3.0",
+ "mini-css-extract-plugin": "^1.3.1",
"node-sass": "5.0.0",
"nodemon": "^2.0.6",
"npm-run-all": "^4.1.5",
- "postcss": "^8.1.6",
+ "postcss": "^8.1.7",
"postcss-cli": "^8.2.0",
"rimraf": "^3.0.2"
},
diff --git a/packages/common/src/global-grid-options.ts b/packages/common/src/global-grid-options.ts
index 71f1bf5ec..7954eb019 100644
--- a/packages/common/src/global-grid-options.ts
+++ b/packages/common/src/global-grid-options.ts
@@ -96,13 +96,17 @@ export const GlobalGridOptions: GridOption = {
defaultSlickgridEventPrefix: '',
editable: false,
editorTypingDebounce: 450,
- enableEmptyDataWarningMessage: false,
+ enableEmptyDataWarningMessage: true,
emptyDataWarning: {
- class: 'slick-empty-data-warning',
+ className: 'slick-empty-data-warning',
message: 'No data to display.',
messageKey: 'EMPTY_DATA_WARNING_MESSAGE',
- marginTop: 100,
- marginLeft: 10
+ hideFrozenLeftWarning: false,
+ hideFrozenRightWarning: false,
+ leftViewportMarginLeft: '40%',
+ rightViewportMarginLeft: '40%',
+ frozenLeftViewportMarginLeft: '0px',
+ frozenRightViewportMarginLeft: '40%',
},
enableAutoResize: true,
enableAutoSizeColumns: true,
diff --git a/packages/common/src/interfaces/emptyWarning.interface.ts b/packages/common/src/interfaces/emptyWarning.interface.ts
index caff74e55..a318fd845 100644
--- a/packages/common/src/interfaces/emptyWarning.interface.ts
+++ b/packages/common/src/interfaces/emptyWarning.interface.ts
@@ -6,11 +6,23 @@ export interface EmptyWarning {
messageKey?: string;
/** DOM Element class name, defaults to "empty-data-warning" */
- class?: string;
+ className?: string;
- /** Top margin position, number in pixel, of where the warning message will be displayed, default calculation is (header title row + filter row + 5px) */
- marginTop?: number;
+ /** Defaults to False, when using a frozen/pinned grid, do we want to hide the warning on the left side? */
+ hideFrozenLeftWarning?: boolean;
- /** Left margin position, number in pixel, of where the warning message will be displayed, defaults to 10px */
- marginLeft?: number;
+ /** Defaults to False, when using a frozen/pinned grid, do we want to hide the warning on the right side? */
+ hideFrozenRightWarning?: boolean;
+
+ /** Defaults to "40%", what is the margin-left CSS style to use when we have a regular grid (non-frozen grid)? */
+ leftViewportMarginLeft?: number | string;
+
+ /** Defaults to "10px", what is the margin-left CSS style to use when the grid is a frozen/pinned grid? */
+ frozenLeftViewportMarginLeft?: number | string;
+
+ /** Defaults to "40%", what is the margin-left CSS style to use when we have a regular grid (non-frozen grid)? */
+ rightViewportMarginLeft?: number | string;
+
+ /** Defaults to "10px", what is the margin-left CSS style to use when the grid is a frozen/pinned grid? */
+ frozenRightViewportMarginLeft?: number | string;
}
diff --git a/packages/common/src/services/groupingAndColspan.service.ts b/packages/common/src/services/groupingAndColspan.service.ts
index c56341afd..293bda520 100644
--- a/packages/common/src/services/groupingAndColspan.service.ts
+++ b/packages/common/src/services/groupingAndColspan.service.ts
@@ -135,9 +135,8 @@ export class GroupingAndColspanService {
let header;
let lastColumnGroup = '';
let widthTotal = 0;
- const frozenColumn = this._gridOptions?.frozenColumn ?? -1;
const frozenHeaderWidthCalcDifferential = this._gridOptions?.frozenHeaderWidthCalcDifferential ?? 0;
- const isFrozenGrid = frozenColumn >= 0;
+ const isFrozenGrid = (this._gridOptions?.frozenRow !== undefined && this._gridOptions.frozenRow >= 0);
for (let i = start; i < end; i++) {
colDef = this._columnDefinitions[i];
diff --git a/packages/common/src/styles/_variables.scss b/packages/common/src/styles/_variables.scss
index f1ba8ecff..a7d651e1c 100644
--- a/packages/common/src/styles/_variables.scss
+++ b/packages/common/src/styles/_variables.scss
@@ -868,4 +868,6 @@ $empty-data-warning-font-family: $font-family !default;
$empty-data-warning-font-size: calc(#{$font-size-base} + 2px) !default;
$empty-data-warning-font-style: italic !default;
$empty-data-warning-line-height: 18px !default;
-$empty-data-warning-z-index: 9999 !default;
+$empty-data-warning-margin: 0px !default;
+$empty-data-warning-padding: 8px !default;
+$empty-data-warning-z-index: 10 !default;
diff --git a/packages/common/src/styles/slick-component.scss b/packages/common/src/styles/slick-component.scss
index c72adba4f..8a9f2be4f 100644
--- a/packages/common/src/styles/slick-component.scss
+++ b/packages/common/src/styles/slick-component.scss
@@ -45,13 +45,15 @@
// ----------------------------------------------
.slick-empty-data-warning {
- position: absolute;
+ position: relative;
color: $empty-data-warning-color;
font-family: $empty-data-warning-font-family;
font-size: $empty-data-warning-font-size;
font-style: $empty-data-warning-font-style;
line-height: $empty-data-warning-line-height;
z-index: $empty-data-warning-z-index;
+ margin: $empty-data-warning-margin;
+ padding: $empty-data-warning-padding;
}
diff --git a/packages/vanilla-bundle/dist-grid-bundle-zip/slickgrid-vanilla-bundle.zip b/packages/vanilla-bundle/dist-grid-bundle-zip/slickgrid-vanilla-bundle.zip
index 2094b2bf6..3b9cd7931 100644
Binary files a/packages/vanilla-bundle/dist-grid-bundle-zip/slickgrid-vanilla-bundle.zip and b/packages/vanilla-bundle/dist-grid-bundle-zip/slickgrid-vanilla-bundle.zip differ
diff --git a/packages/vanilla-bundle/package.json b/packages/vanilla-bundle/package.json
index 11f7adb73..3463d1c74 100644
--- a/packages/vanilla-bundle/package.json
+++ b/packages/vanilla-bundle/package.json
@@ -52,7 +52,7 @@
"isomorphic-fetch": "^3.0.0"
},
"devDependencies": {
- "@types/webpack": "^4.41.24",
+ "@types/webpack": "^4.41.25",
"archiver": "^5.0.2",
"cross-env": "^7.0.2",
"dts-bundle-webpack": "^1.0.2",
diff --git a/packages/vanilla-bundle/src/components/__tests__/slick-empty-warning.spec.ts b/packages/vanilla-bundle/src/components/__tests__/slick-empty-warning.spec.ts
index fde11be89..b6bf3b01e 100644
--- a/packages/vanilla-bundle/src/components/__tests__/slick-empty-warning.spec.ts
+++ b/packages/vanilla-bundle/src/components/__tests__/slick-empty-warning.spec.ts
@@ -1,4 +1,4 @@
-import { GridOption, SlickGrid } from '@slickgrid-universal/common';
+import { EmptyWarning, GridOption, SlickGrid } from '@slickgrid-universal/common';
import { SlickEmptyWarningComponent } from '../slick-empty-warning.component';
import { TranslateServiceStub } from '../../../../../test/translateServiceStub';
@@ -6,7 +6,7 @@ const GRID_UID = 'slickgrid_123456';
const mockGridOptions = {
enableTranslate: false,
- showCustomFooter: true,
+ frozenRow: 0,
} as GridOption;
const gridStub = {
@@ -23,7 +23,13 @@ describe('Slick-Empty-Warning Component', () => {
beforeEach(() => {
div = document.createElement('div');
+ const canvasLeft = document.createElement('div');
+ const canvasRight = document.createElement('div');
+ canvasLeft.className = 'grid-canvas grid-canvas-left';
+ canvasRight.className = 'grid-canvas grid-canvas-right';
div.className = GRID_UID;
+ div.appendChild(canvasLeft);
+ div.appendChild(canvasRight);
document.body.appendChild(div);
translateService = new TranslateServiceStub();
@@ -44,43 +50,183 @@ describe('Slick-Empty-Warning Component', () => {
component = new SlickEmptyWarningComponent(gridStub);
component.showEmptyDataMessage(false);
- const componentElm = document.querySelector('div.slickgrid_123456.slick-empty-data-warning') as HTMLSelectElement;
+ const componentLeftElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
+ const componentRightElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-right .slick-empty-data-warning') as HTMLSelectElement;
expect(component).toBeTruthy();
expect(component.constructor).toBeDefined();
- expect(componentElm).toBeFalsy();
+ expect(componentLeftElm).toBeFalsy();
+ expect(componentRightElm).toBeFalsy();
});
- it('should expect the Slick-Empty-Warning to be created and rendered and passing true as 2nd argument', () => {
+ it('should expect the Slick-Empty-Warning to be created in both viewports and rendered and passing true as 2nd argument', () => {
component = new SlickEmptyWarningComponent(gridStub);
component.showEmptyDataMessage(true);
- const componentElm = document.querySelector('div.slickgrid_123456.slick-empty-data-warning') as HTMLSelectElement;
+ const componentLeftElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
+ const componentRightElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-right .slick-empty-data-warning') as HTMLSelectElement;
+
+ expect(component).toBeTruthy();
+ expect(component.constructor).toBeDefined();
+ expect(componentLeftElm).toBeTruthy();
+ expect(componentLeftElm.style.display).toBe('block');
+ expect(componentRightElm.style.display).toBe('block');
+ expect(componentLeftElm.textContent).toBe('No data to display.');
+ expect(componentRightElm.textContent).toBe('No data to display.');
+ });
+
+ it('should expect the Slick-Empty-Warning to be created in both viewports when using Frozen Grid but NOT displayed on left when "hideFrozenLeftWarning" flag is enabled', () => {
+ mockGridOptions.frozenRow = 2;
+ (mockGridOptions.emptyDataWarning as EmptyWarning).hideFrozenLeftWarning = true;
+ (mockGridOptions.emptyDataWarning as EmptyWarning).hideFrozenRightWarning = false;
+ component = new SlickEmptyWarningComponent(gridStub);
+ component.showEmptyDataMessage(true);
+
+ const componentLeftElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
+ const componentRightElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-right .slick-empty-data-warning') as HTMLSelectElement;
+
+ expect(component).toBeTruthy();
+ expect(component.constructor).toBeDefined();
+ expect(componentLeftElm).toBeTruthy();
+ expect(componentLeftElm.style.display).toBe('none');
+ expect(componentRightElm.style.display).toBe('block');
+ expect(componentLeftElm.style.marginLeft).toBe('10px');
+ expect(componentRightElm.style.marginLeft).toBe('10px');
+ expect(componentLeftElm.textContent).toBe('No data to display.');
+ expect(componentRightElm.textContent).toBe('No data to display.');
+ });
+
+ it('should expect the Slick-Empty-Warning to be created and use different left margin when "leftViewportMarginLeft" is set', () => {
+ mockGridOptions.frozenRow = -1;
+ (mockGridOptions.emptyDataWarning as EmptyWarning).leftViewportMarginLeft = '40%';
+ component = new SlickEmptyWarningComponent(gridStub);
+ component.showEmptyDataMessage(true);
+
+ const componentLeftElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
+ const componentRightElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-right .slick-empty-data-warning') as HTMLSelectElement;
+
+ expect(component).toBeTruthy();
+ expect(component.constructor).toBeDefined();
+ expect(componentLeftElm).toBeTruthy();
+ expect(componentLeftElm.style.display).toBe('block');
+ expect(componentRightElm.style.display).toBe('block');
+ expect(componentLeftElm.style.marginLeft).toBe('40%');
+ expect(componentRightElm.style.marginLeft).toBe('0px');
+ expect(componentLeftElm.textContent).toBe('No data to display.');
+ expect(componentRightElm.textContent).toBe('No data to display.');
+ });
+
+ it('should expect the Slick-Empty-Warning to be created and use different left margin when "rightViewportMarginLeft" is set', () => {
+ mockGridOptions.frozenRow = -1;
+ (mockGridOptions.emptyDataWarning as EmptyWarning).rightViewportMarginLeft = '40%';
+ jest.spyOn(gridStub, 'getOptions').mockReturnValue(mockGridOptions);
+
+ component = new SlickEmptyWarningComponent(gridStub);
+ component.showEmptyDataMessage(true);
+
+ const componentLeftElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
+ const componentRightElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-right .slick-empty-data-warning') as HTMLSelectElement;
+
+ expect(component).toBeTruthy();
+ expect(component.constructor).toBeDefined();
+ expect(componentLeftElm).toBeTruthy();
+ expect(componentLeftElm.style.display).toBe('block');
+ expect(componentRightElm.style.display).toBe('block');
+ expect(componentLeftElm.style.marginLeft).toBe('0px');
+ expect(componentRightElm.style.marginLeft).toBe('40%');
+ expect(componentLeftElm.textContent).toBe('No data to display.');
+ expect(componentRightElm.textContent).toBe('No data to display.');
+ });
+
+ it('should expect the Slick-Empty-Warning to be created in both viewports and use different left margin when "frozenLeftViewportMarginLeft" is set', () => {
+ mockGridOptions.frozenRow = 2;
+ (mockGridOptions.emptyDataWarning as EmptyWarning).leftViewportMarginLeft = '40%';
+ (mockGridOptions.emptyDataWarning as EmptyWarning).frozenLeftViewportMarginLeft = '15px';
+ component = new SlickEmptyWarningComponent(gridStub);
+ component.showEmptyDataMessage(true);
+
+ const componentLeftElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
+ const componentRightElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-right .slick-empty-data-warning') as HTMLSelectElement;
+
+ expect(component).toBeTruthy();
+ expect(component.constructor).toBeDefined();
+ expect(componentLeftElm).toBeTruthy();
+ expect(componentLeftElm.style.display).toBe('block');
+ expect(componentRightElm.style.display).toBe('block');
+ expect(componentLeftElm.style.marginLeft).toBe('15px');
+ expect(componentRightElm.style.marginLeft).toBe('10px');
+ expect(componentLeftElm.textContent).toBe('No data to display.');
+ expect(componentRightElm.textContent).toBe('No data to display.');
+ });
+
+ it('should expect the Slick-Empty-Warning to be created in both viewports and use different left margin when "frozenRightViewportMarginLeft" is set', () => {
+ mockGridOptions.frozenRow = 2;
+ (mockGridOptions.emptyDataWarning as EmptyWarning).leftViewportMarginLeft = '40%';
+ (mockGridOptions.emptyDataWarning as EmptyWarning).frozenRightViewportMarginLeft = '22px';
+ component = new SlickEmptyWarningComponent(gridStub);
+ component.showEmptyDataMessage(true);
+
+ const componentLeftElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
+ const componentRightElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-right .slick-empty-data-warning') as HTMLSelectElement;
+
+ expect(component).toBeTruthy();
+ expect(component.constructor).toBeDefined();
+ expect(componentLeftElm).toBeTruthy();
+ expect(componentLeftElm.style.display).toBe('block');
+ expect(componentRightElm.style.display).toBe('block');
+ expect(componentLeftElm.style.marginLeft).toBe('10px');
+ expect(componentRightElm.style.marginLeft).toBe('22px');
+ expect(componentLeftElm.textContent).toBe('No data to display.');
+ expect(componentRightElm.textContent).toBe('No data to display.');
+ });
+
+ it('should expect the Slick-Empty-Warning to be created in both viewports when using Frozen Grid but NOT displayed on right when "hideFrozenRightWarning" flag is enabled', () => {
+ mockGridOptions.frozenRow = 2;
+ (mockGridOptions.emptyDataWarning as EmptyWarning).hideFrozenLeftWarning = false;
+ (mockGridOptions.emptyDataWarning as EmptyWarning).hideFrozenRightWarning = true;
+ component = new SlickEmptyWarningComponent(gridStub);
+ component.showEmptyDataMessage(true);
+
+ const componentLeftElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
+ const componentRightElm = document.querySelector('div.slickgrid_123456 .grid-canvas.grid-canvas-right .slick-empty-data-warning') as HTMLSelectElement;
+
+ expect(component).toBeTruthy();
+ expect(component.constructor).toBeDefined();
+ expect(componentLeftElm).toBeTruthy();
+ expect(componentLeftElm.style.display).toBe('block');
+ expect(componentRightElm.style.display).toBe('none');
+ expect(componentLeftElm.textContent).toBe('No data to display.');
+ expect(componentRightElm.textContent).toBe('No data to display.');
+ });
+
+ it('should expect the Slick-Empty-Warning to change some options and display a different message when provided as an option', () => {
+ const mockOptions = { message: ' No Record found.', className: 'custom-class', marginTop: 22, marginLeft: 11 };
+ component = new SlickEmptyWarningComponent(gridStub);
+ component.showEmptyDataMessage(true, mockOptions);
+
+ const componentElm = document.querySelector('div.slickgrid_123456 .grid-canvas .custom-class') as HTMLSelectElement;
expect(component).toBeTruthy();
expect(component.constructor).toBeDefined();
expect(componentElm).toBeTruthy();
expect(componentElm.style.display).toBe('block');
- expect(componentElm.textContent).toBe('No data to display.');
+ expect(componentElm.classList.contains('custom-class')).toBeTruthy();
+ expect(componentElm.innerHTML).toBe(' No Record found.');
});
- it('should expect the Slick-Empty-Warning to change some options and display a different message when provided as an option', () => {
- const mockGridPosition = { top: 500, left: 42, bottom: 34, right: 15, height: 800, width: 450, visible: true };
- const mockOptions = { message: 'No Record found.', class: 'custom-class', marginTop: 22, marginLeft: 11 };
- jest.spyOn(gridStub, 'getGridPosition').mockReturnValue(mockGridPosition);
+ it('should expect the Slick-Empty-Warning provide html text and expect script to be sanitized out of the final html', () => {
+ const mockOptions = { message: ` No Record found.`, className: 'custom-class', marginTop: 22, marginLeft: 11 };
component = new SlickEmptyWarningComponent(gridStub);
component.showEmptyDataMessage(true, mockOptions);
- const componentElm = document.querySelector('div.slickgrid_123456.custom-class') as HTMLSelectElement;
+ const componentElm = document.querySelector('div.slickgrid_123456 .grid-canvas .custom-class') as HTMLSelectElement;
expect(component).toBeTruthy();
expect(component.constructor).toBeDefined();
expect(componentElm).toBeTruthy();
expect(componentElm.style.display).toBe('block');
- expect(componentElm.style.top).toBe(`${mockGridPosition.top + 22}px`); // 500 + 22
- expect(componentElm.style.left).toBe(`${mockGridPosition.left + 11}px`); // 42 + 11
expect(componentElm.classList.contains('custom-class')).toBeTruthy();
- expect(componentElm.textContent).toBe('No Record found.');
+ expect(componentElm.innerHTML).toBe(' No Record found.');
});
it('should expect the Slick-Empty-Warning message to be translated to French when providing a Translater Service and "messageKey" property', () => {
@@ -89,7 +235,7 @@ describe('Slick-Empty-Warning Component', () => {
component = new SlickEmptyWarningComponent(gridStub, translateService);
component.showEmptyDataMessage(true);
- const componentElm = document.querySelector('div.slickgrid_123456.slick-empty-data-warning') as HTMLSelectElement;
+ const componentElm = document.querySelector('div.slickgrid_123456 .grid-canvas .slick-empty-data-warning') as HTMLSelectElement;
expect(component).toBeTruthy();
expect(component.constructor).toBeDefined();
diff --git a/packages/vanilla-bundle/src/components/slick-empty-warning.component.ts b/packages/vanilla-bundle/src/components/slick-empty-warning.component.ts
index fc0a98ac6..f3d06f687 100644
--- a/packages/vanilla-bundle/src/components/slick-empty-warning.component.ts
+++ b/packages/vanilla-bundle/src/components/slick-empty-warning.component.ts
@@ -1,7 +1,18 @@
-import { EmptyWarning, getHtmlElementOffset, GridOption, sanitizeTextByAvailableSanitizer, SlickGrid, TranslaterService } from '@slickgrid-universal/common';
+import {
+ EmptyWarning,
+ GridOption,
+ sanitizeTextByAvailableSanitizer,
+ SlickGrid,
+ SlickNamespace,
+ TranslaterService
+} from '@slickgrid-universal/common';
+
+// using external non-typed js libraries
+declare const Slick: SlickNamespace;
export class SlickEmptyWarningComponent {
- private _warningElement: HTMLDivElement | null;
+ private _warningLeftElement: HTMLDivElement | null;
+ private _warningRightElement: HTMLDivElement | null;
/** Getter for the Grid Options pulled through the Grid Object */
get gridOptions(): GridOption {
@@ -11,8 +22,10 @@ export class SlickEmptyWarningComponent {
constructor(private grid: SlickGrid, private translaterService?: TranslaterService) { }
dispose() {
- this._warningElement?.remove();
- this._warningElement = null;
+ this._warningLeftElement?.remove();
+ this._warningRightElement?.remove();
+ this._warningLeftElement = null;
+ this._warningRightElement = null;
}
/**
@@ -25,50 +38,72 @@ export class SlickEmptyWarningComponent {
const gridUid = this.grid.getUID();
const defaultMessage = 'No data to display.';
const mergedOptions: EmptyWarning = { message: defaultMessage, ...this.gridOptions.emptyDataWarning, ...options };
- const emptyDataClassName = mergedOptions?.class ?? 'slick-empty-data-warning';
- const finalClassNames = [gridUid, emptyDataClassName];
- this._warningElement = document.querySelector(`.${finalClassNames.join('.')}`);
-
- // calculate margins
- const gridHeaderFilterRowHeight = this.gridOptions?.headerRowHeight ?? 30; // filter row height
- const headerRowCount = 2; // header title row is calculated by SASS and defined as (17px * headerRowCount + paddingTopBottom)
- const headerRowPaddingTopBottom = 10; // 5px (2x for both top/bottom), this is different in each SASS Theme
- const headerRowHeight = 17 * headerRowCount + headerRowPaddingTopBottom;
+ const emptyDataClassName = mergedOptions?.className ?? 'slick-empty-data-warning';
+ this._warningLeftElement = document.querySelector(`.${emptyDataClassName}`);
+ const gridCanvasLeftElm = document.querySelector(`.${gridUid} .grid-canvas.grid-canvas-left`);
+ const gridCanvasRightElm = document.querySelector(`.${gridUid} .grid-canvas.grid-canvas-right`);
+ const leftElementMarginLeft = mergedOptions.leftViewportMarginLeft ?? 0;
+ const rightElementMarginLeft = mergedOptions.rightViewportMarginLeft ?? 0;
+ const leftElementFrozenMarginLeft = mergedOptions.frozenLeftViewportMarginLeft ?? 10;
+ const rightElementFrozenMarginLeft = mergedOptions.frozenRightViewportMarginLeft ?? 10;
+ const isFrozenGrid = (this.gridOptions?.frozenRow !== undefined && this.gridOptions.frozenRow >= 0);
+ const leftViewportMarginLeft = typeof leftElementMarginLeft === 'string' ? leftElementMarginLeft : `${leftElementMarginLeft}px`;
+ const rightViewportMarginLeft = typeof rightElementMarginLeft === 'string' ? rightElementMarginLeft : `${rightElementMarginLeft}px`;
+
+ if (!this._warningLeftElement && !isShowing) {
+ return false;
+ }
+
+ // warning message could come from a translation key or by the warning options
let warningMessage = mergedOptions.message;
if (this.gridOptions.enableTranslate && this.translaterService && mergedOptions?.messageKey) {
warningMessage = this.translaterService.translate(mergedOptions.messageKey);
}
- const preHeaderRowHeight = this.gridOptions.showPreHeaderPanel && this.gridOptions.preHeaderPanelHeight || 0;
- const marginTop = (mergedOptions.marginTop ?? (headerRowHeight + gridHeaderFilterRowHeight + 5)) + preHeaderRowHeight;
- const marginLeft = mergedOptions.marginLeft ?? 10;
- if (!this._warningElement && !isShowing) {
- return isShowing;
- }
-
- if (!this._warningElement) {
+ if (!this._warningLeftElement && gridCanvasLeftElm && gridCanvasRightElm) {
const sanitizedOptions = this.gridOptions && this.gridOptions.sanitizeHtmlOptions || {};
const sanitizedText = sanitizeTextByAvailableSanitizer(this.gridOptions, warningMessage, sanitizedOptions);
- this._warningElement = document.createElement('div');
- this._warningElement.className = finalClassNames.join(' ');
- this._warningElement.innerHTML = sanitizedText;
- document.body.appendChild(this._warningElement);
+ this._warningLeftElement = document.createElement('div');
+ this._warningLeftElement.classList.add(emptyDataClassName);
+ this._warningLeftElement.classList.add('left');
+ this._warningLeftElement.innerHTML = sanitizedText;
+
+ // clone the warning element and add the "right" class to it so we can distinguish
+ this._warningRightElement = this._warningLeftElement.cloneNode(true) as HTMLDivElement;
+ this._warningRightElement.classList.add('right');
+
+ // append both warning elements to both left/right canvas
+ gridCanvasRightElm.appendChild(this._warningRightElement);
+ gridCanvasLeftElm.appendChild(this._warningLeftElement);
}
// if we did find the Slick-Empty-Warning element then we'll display/hide at the grid position with some margin offsets (we need to position under the headerRow and filterRow)
- if (this._warningElement) {
- if (isShowing) {
- const gridPosition = this.grid.getGridPosition();
- const gridOffset = getHtmlElementOffset(document.querySelector(`.${this.grid.getUID()}`) as HTMLDivElement);
-
- // SF seems to have problem with getGridPosition() so we can use getHtmlElementOffset when that happens
- const gridPosTop = !isNaN(gridPosition.top) ? gridPosition.top : (gridOffset?.top ?? 0);
- const gridPosLeft = !isNaN(gridPosition.left) ? gridPosition.left : (gridOffset?.left ?? 0);
- this._warningElement.style.top = `${gridPosTop + marginTop}px`;
- this._warningElement.style.left = `${gridPosLeft + marginLeft}px`;
+ // when using a frozen/pinned grid, we also have extra options to hide left/right message
+ if (this._warningLeftElement) {
+ // display/hide right/left messages
+ let leftDisplay = isShowing ? 'block' : 'none';
+ if (isFrozenGrid && isShowing) {
+ leftDisplay = (mergedOptions.hideFrozenLeftWarning) ? 'none' : 'block';
+ }
+ this._warningLeftElement.style.display = leftDisplay;
+
+ // use correct left margin (defaults to 40% on regular grid or 10px on frozen grid)
+ const leftFrozenMarginLeft = typeof leftElementFrozenMarginLeft === 'string' ? leftElementFrozenMarginLeft : `${leftElementFrozenMarginLeft}px`;
+ this._warningLeftElement.style.marginLeft = isFrozenGrid ? leftFrozenMarginLeft : leftViewportMarginLeft;
+ }
+
+ if (this._warningRightElement) {
+ // use correct left margin (defaults to 40% on regular grid or 10px on frozen grid)
+ let rightDisplay = isShowing ? 'block' : 'none';
+ if (isFrozenGrid && isShowing) {
+ rightDisplay = (mergedOptions.hideFrozenRightWarning) ? 'none' : 'block';
}
- this._warningElement.style.display = isShowing ? 'block' : 'none';
+ this._warningRightElement.style.display = rightDisplay;
+
+ // use correct left margin (defaults to 40% on regular grid or 10px on frozen grid)
+ const rightFrozenMarginLeft = typeof rightElementFrozenMarginLeft === 'string' ? rightElementFrozenMarginLeft : `${rightElementFrozenMarginLeft}px`;
+ this._warningRightElement.style.marginLeft = isFrozenGrid ? rightFrozenMarginLeft : rightViewportMarginLeft;
}
return isShowing;
diff --git a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts
index f52d07cab..8b61ddf47 100644
--- a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts
+++ b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts
@@ -423,7 +423,7 @@ export class SlickVanillaGridBundle {
}
initialization(gridContainerElm: HTMLElement, eventHandler: SlickEventHandler) {
- if (this.gridOptions?.frozenRow !== undefined && this.gridOptions?.frozenRow >= 0) {
+ if (this.gridOptions?.frozenRow !== undefined && this.gridOptions.frozenRow >= 0) {
this.loadJqueryMousewheelDynamically();
}
diff --git a/packages/vanilla-bundle/src/salesforce-global-grid-options.ts b/packages/vanilla-bundle/src/salesforce-global-grid-options.ts
index 476880b47..18ece24e7 100644
--- a/packages/vanilla-bundle/src/salesforce-global-grid-options.ts
+++ b/packages/vanilla-bundle/src/salesforce-global-grid-options.ts
@@ -12,12 +12,8 @@ export const SalesforceGlobalGridOptions = {
},
datasetIdPropertyName: 'Id',
defaultFilterPlaceholder: '',
- enableEmptyDataWarningMessage: false,
emptyDataWarning: {
- class: 'slick-empty-data-warning',
message: ` No data to display.`,
- marginTop: 90,
- marginLeft: 10
},
enableAutoTooltip: true,
enableDeepCopyDatasetOnPageLoad: true,