diff --git a/packages/devextreme/js/__internal/grids/grid_core/m_utils.ts b/packages/devextreme/js/__internal/grids/grid_core/m_utils.ts index 319552134421..b75a5e9e6318 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/m_utils.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/m_utils.ts @@ -23,6 +23,8 @@ import type { ColumnPoint } from '@ts/grids/grid_core/m_types'; import { isEqualSelectors, isSelectorEqualWithCallback } from './utils/index'; +const BASE_LOAD_PANEL_Z_INDEX = 1000; + const DATAGRID_SELECTION_DISABLED_CLASS = 'dx-selection-disabled'; const DATAGRID_GROUP_OPENED_CLASS = 'dx-datagrid-group-opened'; const DATAGRID_GROUP_CLOSED_CLASS = 'dx-datagrid-group-closed'; @@ -230,6 +232,7 @@ export default { shading: false, message: loadPanelOptions.text, container: $container, + zIndex: BASE_LOAD_PANEL_Z_INDEX, }, loadPanelOptions); that._loadPanel = that._createComponent($('
').appendTo($container), LoadPanel, loadPanelOptions); diff --git a/packages/devextreme/js/__internal/ui/overlay/m_overlay.ts b/packages/devextreme/js/__internal/ui/overlay/m_overlay.ts index 20ccc22974ad..4d27789c984e 100644 --- a/packages/devextreme/js/__internal/ui/overlay/m_overlay.ts +++ b/packages/devextreme/js/__internal/ui/overlay/m_overlay.ts @@ -90,6 +90,8 @@ interface OverlayProperties extends Properties { restorePosition?: boolean; + zIndex?: number; + _fixWrapperPosition?: boolean; _skipContentPositioning?: boolean; @@ -722,24 +724,42 @@ class Overlay< this._toggleSubscriptions(visible); } + _handleZIndexOptionChanged(): void { + const { zIndex } = this.option(); + + this._zIndex = zIndex ?? zIndexPool.create(this._zIndexInitValue()); + + this._updateZIndexStackPosition(this._isVisible()); + } + _updateZIndexStackPosition(pushToStack: boolean): void { const overlayStack = this._overlayStack(); // @ts-expect-error ts-error const index = overlayStack.indexOf(this); + const isInStack = index !== -1; + const { zIndex } = this.option(); - if (pushToStack) { - if (index === -1) { - this._zIndex = zIndexPool.create(this._zIndexInitValue()); - // @ts-expect-error ts-error - overlayStack.push(this); + if (!pushToStack) { + if (isInStack) { + overlayStack.splice(index, 1); + zIndexPool.remove(this._zIndex); } - this._$wrapper.css('zIndex', this._zIndex); - this._$content.css('zIndex', this._zIndex); - } else if (index !== -1) { - overlayStack.splice(index, 1); - zIndexPool.remove(this._zIndex); + return; } + + if (!isInStack) { + this._zIndex = zIndex ?? zIndexPool.create(this._zIndexInitValue()); + // @ts-expect-error this and Overlay have no overlap + overlayStack.push(this); + } + + this._updateZIndex(); + } + + _updateZIndex(): void { + this._$wrapper.css('zIndex', this._zIndex); + this._$content.css('zIndex', this._zIndex); } _toggleShading(visible?: boolean): void { @@ -1319,6 +1339,9 @@ class Overlay< this._initHideTopOverlayHandler(value); this._toggleHideTopOverlayCallback(this.option('visible')); break; + case 'zIndex': + this._handleZIndexOptionChanged(); + break; case 'hideOnParentScroll': case '_hideOnParentScrollTarget': { const { visible } = this.option(); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataGrid.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataGrid.tests.js index 91e9931ccd9d..f8c2ea15867e 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataGrid.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataGrid.tests.js @@ -1275,6 +1275,21 @@ QUnit.module('Initialization', baseModuleConfig, () => { // assert assert.strictEqual(onContentReadySpy.callCount, 1, 'onContentReadySpy call count'); }); + + QUnit.test('Load panel has custom z-index (T1308742)', function(assert) { + const dataGrid = createDataGrid({ + dataSource: { + load: function() { + return; + } + } + }); + + const loadPanel = dataGrid.getView('rowsView')._loadPanel; + const loadPanelZIndex = loadPanel._zIndex; + + assert.strictEqual(loadPanelZIndex, 1000, 'load z-index is set to 1000 by default'); + }); }); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets/overlay.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets/overlay.tests.js index 607f99620619..1c8404f8b9c4 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets/overlay.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets/overlay.tests.js @@ -3108,6 +3108,50 @@ testModule('API', moduleConfig, () => { assert.strictEqual(resizeStub.callCount, 1, '\'dxresize\' event handler was called'); resizeStub.restore(); }); + + test('Overlay uses custom zIndex on init if zIndex option is provided', function(assert) { + const overlay = $('#overlay').dxOverlay({ + visible: true, + zIndex: 2000 + }).dxOverlay('instance'); + + const contentZIndex = Number(getComputedStyle(overlay.$content()[0]).zIndex); + + assert.strictEqual(contentZIndex, 2000, 'custom zIndex assigned'); + }); + + test('Changing zIndex option replaces old pool zIndex with custom', function(assert) { + const overlay = $('#overlay').dxOverlay({ + visible: true + }).dxOverlay('instance'); + + const initialZIndex = Number(getComputedStyle(overlay.$content()[0]).zIndex); + + assert.strictEqual(initialZIndex, 1501, 'overlay has initial pool zIndex'); + + overlay.option('zIndex', 5000); + + const finalZIndex = Number(getComputedStyle(overlay.$content()[0]).zIndex); + + assert.strictEqual(finalZIndex, 5000, 'custom zIndex applied'); + }); + + test('Changing zIndex option to undefined resets the default pool zIndex', function(assert) { + const overlay = $('#overlay').dxOverlay({ + visible: true, + zIndex: 5000 + }).dxOverlay('instance'); + + const initialZIndex = Number(getComputedStyle(overlay.$content()[0]).zIndex); + + assert.strictEqual(initialZIndex, 5000, 'overlay has custom zIndex'); + + overlay.option('zIndex', undefined); + + const finalZIndex = Number(getComputedStyle(overlay.$content()[0]).zIndex); + + assert.strictEqual(finalZIndex, 1501, 'initial pool zIndex applied'); + }); });