From c4303483b7995d0e113286c271da25d6a485c87d Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 20 Mar 2025 18:03:33 +0200 Subject: [PATCH] modal ref --- client/src/ui.js | 100 +++++++++++++++++++------ frontend/less/espo/elements/modal.less | 21 ++++-- package-lock.json | 10 +-- package.json | 2 +- 4 files changed, 101 insertions(+), 32 deletions(-) diff --git a/client/src/ui.js b/client/src/ui.js index 80b0837f40..bf6c9c058f 100644 --- a/client/src/ui.js +++ b/client/src/ui.js @@ -60,6 +60,7 @@ import $ from 'jquery'; * @property {boolean} [maximizeButton] Is maximizable. * @property {function()} [onMaximize] On maximize handler. * @property {function()} [onMinimize] On minimize handler. + * @property {string} [backdropClassName] A backdrop class name. As of v9.1.0. */ /** @@ -80,6 +81,11 @@ import $ from 'jquery'; * @property {string} [title] A title. */ +/** + * @type {Espo.Ui.Dialog[]} + */ +const shownDialogList = []; + /** * @alias Espo.Ui.Dialog */ @@ -92,6 +98,7 @@ class Dialog { onBackdropClick buttons screenWidthXs + backdropClassName /** * @private @@ -187,6 +194,7 @@ class Dialog { 'onClose', 'onBackdropClick', 'maximizeButton', + 'backdropClassName', ]; params.forEach(param => { @@ -701,33 +709,61 @@ class Dialog { return $footer; } + /** + * @internal + * @type {HTMLElement} + */ + _backdropElement + /** * Show. */ show() { - // noinspection JSUnresolvedReference + shownDialogList.push(this); + + // noinspection JSUnresolvedReference,JSUnusedGlobalSymbols this.$el.modal({ - backdrop: this.backdrop, - keyboard: this.keyboard, + backdrop: this.backdrop, + keyboard: this.keyboard, + onBackdropCreate: element => { + this._backdropElement = element; + + if (this.backdropClassName) { + this._backdropElement.classList.add(this.backdropClassName); + } + }, }); this.$el.find('.modal-content').removeClass('hidden'); - const $modalBackdrop = $('.modal-backdrop'); + /*const $modalBackdrop = $('.modal-backdrop'); $modalBackdrop.each((i, el) => { if (i < $modalBackdrop.length - 1) { $(el).addClass('hidden'); } }); - const $modalContainer = $('.modal-container'); $modalContainer.each((i, el) => { if (i < $modalContainer.length - 1) { $(el).addClass('overlaid'); } - }); + });*/ + + for (const [i, dialog] of shownDialogList.entries()) { + if ( + i < shownDialogList.length - 1 && + dialog.getElement() && + dialog.getElement().parentElement + ) { + if (dialog._backdropElement) { + dialog._backdropElement.classList.add('hidden'); + } + + dialog.getElement().parentElement.classList.add('overlaid'); + } + } this.$el.off('click.dismiss.bs.modal'); @@ -767,6 +803,8 @@ class Dialog { /** * Hide. + * + * @todo Check usage. Deprecate? */ hide() { this.$el.find('.modal-content').addClass('hidden'); @@ -774,39 +812,58 @@ class Dialog { /** * Hide with a backdrop. + * + * @todo Test. */ hideWithBackdrop() { - const $modalBackdrop = $('.modal-backdrop'); + // const $modalBackdrop = $('.modal-backdrop'); + //$modalBackdrop.last().addClass('hidden'); + //$($modalBackdrop.get($modalBackdrop.length - 2)).removeClass('hidden'); - $modalBackdrop.last().addClass('hidden'); - $($modalBackdrop.get($modalBackdrop.length - 2)).removeClass('hidden'); + if (this._backdropElement) { + this._backdropElement.classList.add('hidden'); + } - const $modalContainer = $('.modal-container'); + this._hideInternal(); - $($modalContainer.get($modalContainer.length - 2)).removeClass('overlaid'); + //const $modalContainer = $('.modal-container'); + //$($modalContainer.get($modalContainer.length - 2)).removeClass('overlaid'); this.skipRemove = true; - setTimeout(() => { - this.skipRemove = false; - }, 50); + setTimeout(() => this.skipRemove = false, 50); // noinspection JSUnresolvedReference this.$el.modal('hide'); this.$el.find('.modal-content').addClass('hidden'); } + /** + * @private + */ + _hideInternal() { + const findIndex = shownDialogList.findIndex(it => it === this); + + if (findIndex >= 0) { + shownDialogList.splice(findIndex, 1); + } + + const last = shownDialogList[shownDialogList.length - 1]; + + if (last && last._backdropElement) { + last._backdropElement.classList.remove('hidden') + } + + if (last && last.getElement() && last.getElement().parentElement) { + last.getElement().parentElement.classList.remove('overlaid') + } + } + /** * @private */ _close() { - const $modalBackdrop = $('.modal-backdrop'); - - $modalBackdrop.last().removeClass('hidden'); - - const $modalContainer = $('.modal-container'); - - $($modalContainer.get($modalContainer.length - 2)).removeClass('overlaid'); + this._hideInternal(); } /** @@ -953,6 +1010,7 @@ Espo.Ui = { backdrop: backdrop, header: null, className: 'dialog-confirm', + backdropClassName: 'backdrop-confirm', body: '' + message + '', buttonList: [ { diff --git a/frontend/less/espo/elements/modal.less b/frontend/less/espo/elements/modal.less index a16eaf2e01..37709af6e5 100644 --- a/frontend/less/espo/elements/modal.less +++ b/frontend/less/espo/elements/modal.less @@ -135,6 +135,10 @@ background-color: var(--modal-backdrop-bg); backdrop-filter: var(--modal-backdrop-filter); opacity: 1; + + &.backdrop-confirm { + z-index: 1051; + } } .modal-dialog > .modal-content { @@ -163,12 +167,19 @@ z-index: 4; } -.dialog-confirm .modal-footer > .main-btn-group { - float: right; -} -.dialog-confirm .modal-footer > .additional-btn-group { - float: left; +.dialog-confirm { + .modal-footer > .main-btn-group { + float: right; + } + + .modal-footer > .additional-btn-group { + float: left; + } + + &.modal { + z-index: 1052; + } } .modal-container { diff --git a/package-lock.json b/package-lock.json index 94a46dafc7..abedb8d453 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "autobahn-espo": "github:yurikuzn/autobahn-espo#0.1.0", "autonumeric": "^4.6.0", "backbone": "^1.3.3", - "bootstrap": "github:yurikuzn/espo-bootstrap#0.1.1", + "bootstrap": "github:yurikuzn/espo-bootstrap#0.1.2", "bootstrap-colorpicker": "^2.5.2", "bootstrap-datepicker": "^1.9.0", "bullbone": "github:espocrm/bullbone#1.3.1", @@ -2454,8 +2454,8 @@ }, "node_modules/bootstrap": { "name": "bootstrap-for-espo", - "version": "0.1.1", - "resolved": "git+ssh://git@github.com/yurikuzn/espo-bootstrap.git#99ba8bcd05ef0021c59179b5d0460624aa5f5976", + "version": "0.1.2", + "resolved": "git+ssh://git@github.com/yurikuzn/espo-bootstrap.git#3de585835afbd1cd89ba0fa72495f2d32291e9c9", "engines": { "node": ">=6" } @@ -9127,8 +9127,8 @@ } }, "bootstrap": { - "version": "git+ssh://git@github.com/yurikuzn/espo-bootstrap.git#99ba8bcd05ef0021c59179b5d0460624aa5f5976", - "from": "bootstrap@github:yurikuzn/espo-bootstrap#0.1.1" + "version": "git+ssh://git@github.com/yurikuzn/espo-bootstrap.git#3de585835afbd1cd89ba0fa72495f2d32291e9c9", + "from": "bootstrap@github:yurikuzn/espo-bootstrap#0.1.2" }, "bootstrap-colorpicker": { "version": "2.5.2", diff --git a/package.json b/package.json index 8d737668c3..87a7515525 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "autobahn-espo": "github:yurikuzn/autobahn-espo#0.1.0", "autonumeric": "^4.6.0", "backbone": "^1.3.3", - "bootstrap": "github:yurikuzn/espo-bootstrap#0.1.1", + "bootstrap": "github:yurikuzn/espo-bootstrap#0.1.2", "bootstrap-colorpicker": "^2.5.2", "bootstrap-datepicker": "^1.9.0", "bullbone": "github:espocrm/bullbone#1.3.1",