Fixed #1169 - Customizable ZIndex Layering

pull/1088/head
Cagatay Civici 2021-04-13 16:59:08 +03:00
parent 3d72768811
commit b910825a84
25 changed files with 324 additions and 106 deletions

View File

@ -15,7 +15,7 @@
<i class="p-autocomplete-loader pi pi-spinner pi-spin" v-if="searching"></i>
<Button ref="dropdownButton" type="button" icon="pi pi-chevron-down" class="p-autocomplete-dropdown" :disabled="$attrs.disabled" @click="onDropdownClick" v-if="dropdown"/>
<Teleport :to="appendTo">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
<div :ref="overlayRef" class="p-autocomplete-panel p-component" :style="{'max-height': scrollHeight}" v-if="overlayVisible" @click="onOverlayClick">
<slot name="header" :value="modelValue" :suggestions="suggestions"></slot>
<ul :id="listId" class="p-autocomplete-items" role="listbox">
@ -43,7 +43,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,UniqueComponentId,ObjectUtils,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,UniqueComponentId,ObjectUtils,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import Button from 'primevue/button';
import Ripple from 'primevue/ripple';
@ -134,7 +134,11 @@ export default {
this.scrollHandler.destroy();
this.scrollHandler = null;
}
this.overlay = null;
if (this.overlay) {
ZIndexUtils.clear(this.overlay);
this.overlay = null;
}
},
updated() {
if (this.overlayVisible) {
@ -151,8 +155,8 @@ export default {
getOptionGroupChildren(optionGroup) {
return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupChildren);
},
onOverlayEnter() {
this.overlay.style.zIndex = String(DomHandler.generateZIndex());
onOverlayEnter(el) {
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
this.alignOverlay();
this.bindOutsideClickListener();
this.bindScrollListener();
@ -164,6 +168,9 @@ export default {
this.unbindResizeListener();
this.overlay = null;
},
onOverlayAfterLeave(el) {
ZIndexUtils.clear(el);
},
alignOverlay() {
let target = this.multiple ? this.$refs.multiContainer : this.$refs.input;
this.overlay.style.minWidth = DomHandler.getOuterWidth(target) + 'px';

View File

@ -4,7 +4,7 @@
:class="inputClass" :style="inputStyle" />
<CalendarButton v-if="showIcon" :icon="icon" tabindex="-1" class="p-datepicker-trigger" :disabled="$attrs.disabled" @click="onButtonClick" type="button" :aria-label="inputFieldValue"/>
<Teleport :to="appendTo" :disabled="inline">
<transition name="p-connected-overlay" @enter="onOverlayEnter($event)" @after-enter="onOverlayEnterComplete" @leave="onOverlayLeave">
<transition name="p-connected-overlay" @enter="onOverlayEnter($event)" @after-enter="onOverlayEnterComplete" @after-leave="onOverlayAfterLeave" @leave="onOverlayLeave">
<div :ref="overlayRef" :class="panelStyleClass" v-if="inline ? true : overlayVisible" :role="inline ? null : 'dialog'" @click="onOverlayClick">
<template v-if="!timeOnly">
<div class="p-datepicker-group-container">
@ -133,7 +133,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import InputText from 'primevue/inputtext';
import Button from 'primevue/button';
@ -342,6 +342,10 @@ export default {
this.scrollHandler.destroy();
this.scrollHandler = null;
}
if (this.overlay && this.autoZIndex) {
ZIndexUtils.clear(this.overlay);
}
this.overlay = null;
},
data() {
@ -523,9 +527,12 @@ export default {
return validMin && validMax && validDate && validDay;
},
onOverlayEnter() {
onOverlayEnter(el) {
if (this.autoZIndex) {
this.overlay.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
if (this.touchUI)
ZIndexUtils.set('modal', el, this.baseZIndex || this.$primevue.config.zIndex.modal);
else
ZIndexUtils.set('overlay', el, this.baseZIndex || this.$primevue.config.zIndex.overlay);
}
this.alignOverlay();
this.$emit('show');
@ -535,6 +542,11 @@ export default {
this.bindScrollListener();
this.bindResizeListener();
},
onOverlayAfterLeave(el) {
if (this.autoZIndex) {
ZIndexUtils.clear(el);
}
},
onOverlayLeave() {
this.unbindOutsideClickListener();
this.unbindScrollListener();

View File

@ -13,7 +13,7 @@
<span class="p-cascadeselect-trigger-icon pi pi-chevron-down"></span>
</div>
<Teleport :to="appendTo">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
<div :ref="overlayRef" class="p-cascadeselect-panel p-component" v-if="overlayVisible" @click="onOverlayClick">
<div class="p-cascadeselect-items-wrapper">
<CascadeSelectSub :options="options" :selectionPath="selectionPath"
@ -28,7 +28,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import CascadeSelectSub from './CascadeSelectSub.vue';
@ -72,7 +72,11 @@ export default {
this.scrollHandler.destroy();
this.scrollHandler = null;
}
this.overlay = null;
if (this.overlay) {
ZIndexUtils.clear(this.overlay);
this.overlay = null;
}
},
mounted() {
this.updateSelectionPath();
@ -163,8 +167,8 @@ export default {
this.$refs.focusInput.focus();
}
},
onOverlayEnter() {
this.overlay.style.zIndex = String(DomHandler.generateZIndex());
onOverlayEnter(el) {
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
this.alignOverlay();
this.bindOutsideClickListener();
this.bindScrollListener();
@ -179,6 +183,9 @@ export default {
this.overlay = null;
this.dirty = false;
},
onOverlayAfterLeave(el) {
ZIndexUtils.clear(el);
},
alignOverlay() {
DomHandler.absolutePosition(this.overlay, this.$el);
this.overlay.style.minWidth = DomHandler.getOuterWidth(this.$el) + 'px';

View File

@ -3,7 +3,7 @@
<input ref="input" type="text" :class="inputClass" readonly="readonly" :tabindex="tabindex" :disabled="disabled"
@click="onInputClick" @keydown="onInputKeydown" v-if="!inline" :aria-labelledby="ariaLabelledBy"/>
<Teleport to="body" :disabled="inline">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
<div :ref="pickerRef" :class="pickerClass" v-if="inline ? true : overlayVisible" @click="onOverlayClick">
<div class="p-colorpicker-content">
<div :ref="colorSelectorRef" class="p-colorpicker-color-selector" @mousedown="onColorMousedown($event)"
@ -24,7 +24,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
export default {
@ -95,6 +95,11 @@ export default {
this.scrollHandler.destroy();
this.scrollHandler = null;
}
if (this.picker && this.autoZIndex) {
ZIndexUtils.clear(this.picker);
}
this.clearRefs();
},
mounted() {
@ -333,7 +338,7 @@ export default {
return hsb;
},
onOverlayEnter() {
onOverlayEnter(el) {
this.updateUI();
this.alignOverlay();
this.bindOutsideClickListener();
@ -341,7 +346,7 @@ export default {
this.bindResizeListener();
if (this.autoZIndex) {
this.picker.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
}
},
onOverlayLeave() {
@ -350,6 +355,11 @@ export default {
this.unbindResizeListener();
this.clearRefs();
},
onOverlayAfterLeave(el) {
if (this.autoZIndex) {
ZIndexUtils.clear(el);
}
},
alignOverlay() {
DomHandler.absolutePosition(this.picker, this.$refs.input);
},

View File

@ -69,6 +69,12 @@ const defaultOptions = {
FilterMatchMode.DATE_BEFORE,
FilterMatchMode.DATE_AFTER
]
},
zIndex: {
modal: 1100,
overlay: 1000,
menu: 1000,
tooltip: 1100
}
};

View File

@ -1,6 +1,6 @@
<template>
<Teleport to="body">
<transition name="p-confirm-popup" @enter="onEnter" @leave="onLeave">
<transition name="p-confirm-popup" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
<div class="p-confirm-popup p-component" v-if="visible" :ref="containerRef" v-bind="$attrs" @click="onOverlayClick">
<div class="p-confirm-popup-content">
<i :class="iconClass" />
@ -17,7 +17,7 @@
<script>
import ConfirmationEventBus from 'primevue/confirmationeventbus';
import {ConnectedOverlayScrollHandler,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import Button from 'primevue/button';
@ -65,8 +65,13 @@ export default {
this.scrollHandler = null;
}
this.unbindResizeListener();
if (this.container) {
ZIndexUtils.clear(this.container);
this.container = null;
}
this.target = null;
this.container = null;
this.confirmation = null;
},
methods: {
@ -84,18 +89,22 @@ export default {
this.visible = false;
},
onEnter() {
onEnter(el) {
this.alignOverlay();
this.bindOutsideClickListener();
this.bindScrollListener();
this.bindResizeListener();
this.container.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
},
onLeave() {
this.unbindOutsideClickListener();
this.unbindScrollListener();
this.unbindResizeListener();
},
onAfterLeave(el) {
ZIndexUtils.clear(el);
},
alignOverlay() {
DomHandler.absolutePosition(this.container, this.target);

View File

@ -1,6 +1,6 @@
<template>
<Teleport :to="appendTo">
<transition name="p-contextmenu" @enter="onEnter" @leave="onLeave">
<transition name="p-contextmenu" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
<div :ref="containerRef" class="p-contextmenu p-component" v-if="visible" v-bind="$attrs">
<ContextMenuSub :model="model" :root="true" @leaf-click="onLeafClick" />
</div>
@ -9,7 +9,7 @@
</template>
<script>
import {DomHandler} from 'primevue/utils';
import {DomHandler,ZIndexUtils} from 'primevue/utils';
import ContextMenuSub from './ContextMenuSub.vue';
export default {
@ -52,6 +52,10 @@ export default {
this.unbindResizeListener();
this.unbindOutsideClickListener();
this.unbindDocumentContextMenuListener();
if (this.container && this.autoZIndex) {
ZIndexUtils.clear(this.container);
}
this.container = null;
},
mounted() {
@ -92,19 +96,24 @@ export default {
hide() {
this.visible = false;
},
onEnter() {
onEnter(el) {
this.position();
this.bindOutsideClickListener();
this.bindResizeListener();
if (this.autoZIndex) {
this.container.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
ZIndexUtils.set('menu', el, this.baseZIndex + this.$primevue.config.zIndex.menu);
}
},
onLeave() {
this.unbindOutsideClickListener();
this.unbindResizeListener();
},
onAfterLeave(el) {
if (this.autoZIndex) {
ZIndexUtils.clear(el);
}
},
position() {
let left = this.pageX + 1;
let top = this.pageY + 1;

View File

@ -29,7 +29,7 @@
</template>
<script>
import {UniqueComponentId,DomHandler} from 'primevue/utils';
import {UniqueComponentId,DomHandler,ZIndexUtils} from 'primevue/utils';
import Ripple from 'primevue/ripple';
export default {
@ -95,8 +95,13 @@ export default {
beforeUnmount() {
this.unbindDocumentState();
this.destroyStyle();
this.container = null;
this.mask = null;
if (this.container && this.autoZIndex) {
ZIndexUtils.clear(this.container);
}
this.container = null;
},
mounted() {
if (this.breakpoints) {
@ -109,7 +114,7 @@ export default {
},
onBeforeEnter(el) {
if (this.autoZIndex) {
el.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
ZIndexUtils.set('modal', el, this.baseZIndex + this.$primevue.config.zIndex.modal);
}
el.setAttribute(this.attributeSelector, '');
@ -127,7 +132,10 @@ export default {
onLeave() {
this.$emit('hide');
},
onAfterLeave() {
onAfterLeave(el) {
if (this.autoZIndex) {
ZIndexUtils.clear(el);
}
this.containerVisible = false;
this.unbindDocumentState();
},

View File

@ -14,7 +14,7 @@
<span class="p-dropdown-trigger-icon pi pi-chevron-down"></span>
</div>
<Teleport :to="appendTo">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
<div :ref="overlayRef" class="p-dropdown-panel p-component" v-if="overlayVisible" @click="onOverlayClick">
<slot name="header" :value="modelValue" :options="visibleOptions"></slot>
<div class="p-dropdown-header" v-if="filter">
@ -58,7 +58,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import {FilterService} from 'primevue/api';
import Ripple from 'primevue/ripple';
@ -133,8 +133,13 @@ export default {
this.scrollHandler.destroy();
this.scrollHandler = null;
}
this.itemsWrapper = null;
this.overlay = null;
if (this.overlay) {
ZIndexUtils.clear(this.overlay);
this.overlay = null;
}
},
methods: {
getOptionLabel(option) {
@ -386,8 +391,8 @@ export default {
onEditableInput(event) {
this.$emit('update:modelValue', event.target.value);
},
onOverlayEnter() {
this.overlay.style.zIndex = String(DomHandler.generateZIndex());
onOverlayEnter(el) {
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
this.scrollValueInView();
this.alignOverlay();
this.bindOutsideClickListener();
@ -408,6 +413,9 @@ export default {
this.itemsWrapper = null;
this.overlay = null;
},
onOverlayAfterLeave(el) {
ZIndexUtils.clear(el);
},
alignOverlay() {
this.overlay.style.minWidth = DomHandler.getOuterWidth(this.$el) + 'px';
DomHandler.absolutePosition(this.overlay, this.$el);

View File

@ -11,7 +11,7 @@
<script>
import GalleriaContent from './GalleriaContent.vue';
import {DomHandler} from 'primevue/utils';
import {DomHandler,ZIndexUtils} from 'primevue/utils';
export default {
inheritAttrs: false,
@ -131,21 +131,25 @@ export default {
DomHandler.removeClass(document.body, 'p-overflow-hidden');
}
this.container = null;
this.mask = null;
if (this.container) {
ZIndexUtils.clear(this.container);
this.container = null;
}
},
methods: {
onBeforeEnter(el) {
el.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
ZIndexUtils.set('modal', el, this.baseZIndex || this.$primevue.config.zIndex.modal);
},
onEnter() {
this.mask.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
onEnter(el) {
this.mask.style.zIndex = String(parseInt(el.style.zIndex, 10) - 1);
DomHandler.addClass(document.body, 'p-overflow-hidden');
},
onBeforeLeave() {
DomHandler.addClass(this.mask, 'p-galleria-mask-leave');
},
onAfterLeave() {
onAfterLeave(el) {
ZIndexUtils.clear(el);
this.containerVisible = false;
DomHandler.removeClass(document.body, 'p-overflow-hidden');
},

View File

@ -1,6 +1,6 @@
<template>
<Teleport :to="appendTo" :disabled="!popup">
<transition name="p-connected-overlay" @enter="onEnter" @leave="onLeave">
<transition name="p-connected-overlay" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
<div :ref="containerRef" :class="containerClass" v-if="popup ? overlayVisible : true" v-bind="$attrs" @click="onOverlayClick">
<ul class="p-menu-list p-reset" role="menu">
<template v-for="(item, i) of model" :key="item.label + i.toString()">
@ -21,7 +21,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import Menuitem from './Menuitem.vue';
@ -68,6 +68,10 @@ export default {
this.scrollHandler = null;
}
this.target = null;
if (this.container && this.autoZIndex) {
ZIndexUtils.clear(this.container);
}
this.container = null;
},
methods: {
@ -101,14 +105,14 @@ export default {
this.overlayVisible = false;
this.target = null;
},
onEnter() {
onEnter(el) {
this.alignOverlay();
this.bindOutsideClickListener();
this.bindResizeListener();
this.bindScrollListener();
if (this.autoZIndex) {
this.container.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
ZIndexUtils.set('menu', el, this.baseZIndex + this.$primevue.config.zIndex.menu);
}
},
onLeave() {
@ -116,6 +120,11 @@ export default {
this.unbindResizeListener();
this.unbindScrollListener();
},
onAfterLeave(el) {
if (this.autoZIndex) {
ZIndexUtils.clear(el);
}
},
alignOverlay() {
DomHandler.absolutePosition(this.container, this.target);
this.container.style.minWidth = DomHandler.getOuterWidth(this.target) + 'px';

View File

@ -15,7 +15,7 @@
<script>
import MenubarSub from './MenubarSub.vue';
import {DomHandler} from 'primevue/utils';
import {ZIndexUtils} from 'primevue/utils';
export default {
props: {
@ -33,11 +33,21 @@ export default {
beforeUnmount() {
this.mobileActive = false;
this.unbindOutsideClickListener();
if (this.$refs.rootmenu && this.$refs.rootmenu.$el) {
ZIndexUtils.clear(this.$refs.rootmenu.$el);
}
},
methods: {
toggle(event) {
this.mobileActive = !this.mobileActive;
this.$refs.rootmenu.$el.style.zIndex = String(DomHandler.generateZIndex());
if (this.mobileActive) {
this.mobileActive = false;
ZIndexUtils.clear(this.$refs.rootmenu.$el);
}
else {
this.mobileActive = true;
ZIndexUtils.set('menu', this.$refs.rootmenu.$el, this.$primevue.config.zIndex.menu);
}
this.bindOutsideClickListener();
event.preventDefault();
},

View File

@ -24,7 +24,7 @@
<span class="p-multiselect-trigger-icon pi pi-chevron-down"></span>
</div>
<Teleport :to="appendTo">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
<div :ref="overlayRef" class="p-multiselect-panel p-component" v-if="overlayVisible" @click="onOverlayClick">
<slot name="header" :value="modelValue" :options="visibleOptions"></slot>
<div class="p-multiselect-header">
@ -93,7 +93,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import {FilterService} from 'primevue/api';
import Ripple from 'primevue/ripple';
@ -166,7 +166,11 @@ export default {
this.scrollHandler.destroy();
this.scrollHandler = null;
}
this.overlay = null;
if (this.overlay) {
ZIndexUtils.clear(this.overlay);
this.overlay = null;
}
},
methods: {
getOptionLabel(option) {
@ -340,8 +344,8 @@ export default {
else
return null;
},
onOverlayEnter() {
this.overlay.style.zIndex = String(DomHandler.generateZIndex());
onOverlayEnter(el) {
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
this.alignOverlay();
this.bindOutsideClickListener();
this.bindScrollListener();
@ -355,6 +359,9 @@ export default {
this.$emit('hide');
this.overlay = null;
},
onOverlayAfterLeave(el) {
ZIndexUtils.clear(el);
},
alignOverlay() {
this.overlay.style.minWidth = DomHandler.getOuterWidth(this.$el) + 'px';
DomHandler.absolutePosition(this.overlay, this.$el);

View File

@ -1,6 +1,6 @@
<template>
<Teleport :to="appendTo">
<transition name="p-overlaypanel" @enter="onEnter" @leave="onLeave">
<transition name="p-overlaypanel" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
<div class="p-overlaypanel p-component" v-if="visible" :ref="containerRef" v-bind="$attrs" @click="onOverlayClick">
<div class="p-overlaypanel-content" @click="onContentClick">
<slot></slot>
@ -14,7 +14,7 @@
</template>
<script>
import {UniqueComponentId,DomHandler,ConnectedOverlayScrollHandler} from 'primevue/utils';
import {UniqueComponentId,DomHandler,ConnectedOverlayScrollHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import Ripple from 'primevue/ripple';
@ -74,6 +74,10 @@ export default {
this.destroyStyle();
this.unbindResizeListener();
this.target = null;
if (this.container && this.autoZIndex) {
ZIndexUtils.clear(this.container);
}
this.container = null;
},
mounted() {
@ -98,7 +102,7 @@ export default {
onContentClick() {
this.selfClick = true;
},
onEnter() {
onEnter(el) {
this.container.setAttribute(this.attributeSelector, '');
this.alignOverlay();
if (this.dismissable) {
@ -109,8 +113,9 @@ export default {
this.bindResizeListener();
if (this.autoZIndex) {
this.container.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
ZIndexUtils.set('overlay', el, this.baseZIndex + this.$primevue.config.zIndex.overlay);
}
OverlayEventBus.on('overlay-click', e => {
if (this.container.contains(e.target)) {
this.selfClick = true;
@ -123,6 +128,11 @@ export default {
this.unbindResizeListener();
OverlayEventBus.off('overlay-click');
},
onAfterLeave(el) {
if (this.autoZIndex) {
ZIndexUtils.clear(el);
}
},
alignOverlay() {
DomHandler.absolutePosition(this.container, this.target);

View File

@ -3,7 +3,7 @@
<PInputText ref="input" :class="inputFieldClass" :style="inputStyle" :type="inputType" :value="modelValue" @input="onInput" @focus="onFocus" @blur="onBlur" @keyup="onKeyUp" v-bind="$attrs" />
<i v-if="toggleMask" :class="toggleIconClass" @click="onMaskToggle" />
<Teleport :to="appendTo">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
<div :ref="overlayRef" class="p-password-panel p-component" v-if="overlayVisible" @click="onOverlayClick">
<slot name="header"></slot>
<slot name="content">
@ -20,7 +20,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import InputText from 'primevue/inputtext';
@ -95,10 +95,15 @@ export default {
this.scrollHandler.destroy();
this.scrollHandler = null;
}
if (this.overlay) {
ZIndexUtils.clear(this.overlay);
this.overlay = null;
}
},
methods: {
onOverlayEnter() {
this.overlay.style.zIndex = String(DomHandler.generateZIndex());
onOverlayEnter(el) {
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
this.alignOverlay();
this.bindScrollListener();
this.bindResizeListener();
@ -108,6 +113,9 @@ export default {
this.unbindResizeListener();
this.overlay = null;
},
onOverlayAfterLeave(el) {
ZIndexUtils.clear(el);
},
alignOverlay() {
this.overlay.style.minWidth = DomHandler.getOuterWidth(this.$refs.input.$el) + 'px';
DomHandler.absolutePosition(this.overlay, this.$refs.input.$el);

View File

@ -1,16 +1,17 @@
<template>
<transition name="p-scrolltop" appear @enter="onEnter">
<button :class="containerClass" v-if="visible" @click="onClick" type="button">
<transition name="p-scrolltop" appear @enter="onEnter" @after-leave="onAfterLeave">
<button :ref="containerRef" :class="containerClass" v-if="visible" @click="onClick" type="button">
<span :class="iconClass"></span>
</button>
</transition>
</template>
<script>
import {DomHandler} from 'primevue/utils';
import {DomHandler,ZIndexUtils} from 'primevue/utils';
export default {
scrollListener: null,
container: null,
data() {
return {
visible: false
@ -45,6 +46,11 @@ export default {
this.unbindDocumentScrollListener();
else if (this.target === 'parent')
this.unbindParentScrollListener();
if (this.container) {
ZIndexUtils.clear(this.container);
this.overlay = null;
}
},
methods: {
onClick() {
@ -86,8 +92,14 @@ export default {
this.scrollListener = null;
}
},
onEnter() {
this.$el.style.zIndex = String(DomHandler.generateZIndex());
onEnter(el) {
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
},
onAfterLeave(el) {
ZIndexUtils.clear(el);
},
containerRef(el) {
this.container = el;
}
},
computed: {

View File

@ -1,7 +1,7 @@
<template>
<Teleport to="body">
<transition name="p-sidebar" @enter="onEnter" @leave="onLeave" appear>
<div :class="containerClass" v-if="visible" ref="container" role="complementary" :aria-modal="modal" v-bind="$attrs">
<transition name="p-sidebar" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave" appear>
<div :class="containerClass" v-if="visible" :ref="containerRef" role="complementary" :aria-modal="modal" v-bind="$attrs">
<div class="p-sidebar-content">
<button class="p-sidebar-close p-link" @click="hide" :aria-label="ariaCloseLabel" v-if="showCloseIcon" type="button" v-ripple>
<span class="p-sidebar-close-icon pi pi-times" />
@ -14,7 +14,7 @@
</template>
<script>
import {DomHandler} from 'primevue/utils';
import {DomHandler,ZIndexUtils} from 'primevue/utils';
import Ripple from 'primevue/ripple';
export default {
@ -56,18 +56,24 @@ export default {
},
mask: null,
maskClickListener: null,
container: null,
beforeUnmount() {
this.destroyModal();
if (this.container && this.autoZIndex) {
ZIndexUtils.clear(this.container);
}
this.container = null;
},
methods: {
hide() {
this.$emit('update:visible', false);
},
onEnter() {
onEnter(el) {
this.$emit('show');
if (this.autoZIndex) {
this.$refs.container.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
ZIndexUtils.set('modal', el, this.baseZIndex || this.$primevue.config.zIndex.modal);
}
this.focus();
if (this.modal && !this.fullScreen) {
@ -81,8 +87,13 @@ export default {
this.disableModality();
}
},
onAfterLeave(el) {
if (this.autoZIndex) {
ZIndexUtils.clear(el);
}
},
focus() {
let focusable = DomHandler.findSingle(this.$refs.container, 'input,button');
let focusable = DomHandler.findSingle(this.container, 'input,button');
if (focusable) {
focusable.focus();
}
@ -91,7 +102,7 @@ export default {
if (!this.mask) {
this.mask = document.createElement('div');
this.mask.setAttribute('class', 'p-sidebar-mask');
this.mask.style.zIndex = String(parseInt(this.$refs.container.style.zIndex, 10) - 1);
this.mask.style.zIndex = String(parseInt(this.container.style.zIndex, 10) - 1);
if (this.dismissable) {
this.bindMaskClickListener();
}
@ -132,6 +143,9 @@ export default {
DomHandler.removeClass(document.body, 'p-overflow-hidden');
this.mask = null;
}
},
containerRef(el) {
this.container = el;
}
},
computed: {

View File

@ -1,6 +1,6 @@
<template>
<Teleport :to="appendTo" :disabled="!popup">
<transition name="p-connected-overlay" @enter="onEnter" @leave="onLeave">
<transition name="p-connected-overlay" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
<div :ref="containerRef" :class="containerClass" v-if="popup ? visible : true" v-bind="$attrs" @click="onOverlayClick">
<TieredMenuSub :model="model" :root="true" :popup="popup" @leaf-click="onLeafClick"/>
</div>
@ -9,7 +9,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import TieredMenuSub from './TieredMenuSub.vue';
@ -56,6 +56,9 @@ export default {
this.scrollHandler = null;
}
this.target = null;
if (this.container && this.autoZIndex) {
ZIndexUtils.clear(this.container);
}
this.container = null;
},
methods: {
@ -80,14 +83,14 @@ export default {
hide() {
this.visible = false;
},
onEnter() {
onEnter(el) {
this.alignOverlay();
this.bindOutsideClickListener();
this.bindResizeListener();
this.bindScrollListener();
if (this.autoZIndex) {
this.container.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
ZIndexUtils.set('menu', el, this.baseZIndex + this.$primevue.config.zIndex.menu);
}
},
onLeave() {
@ -95,6 +98,11 @@ export default {
this.unbindResizeListener();
this.unbindScrollListener();
},
onAfterLeave(el) {
if (this.autoZIndex) {
ZIndexUtils.clear(el);
}
},
alignOverlay() {
DomHandler.absolutePosition(this.container, this.target);
this.container.style.minWidth = DomHandler.getOuterWidth(this.target) + 'px';

View File

@ -11,7 +11,7 @@
<script>
import ToastEventBus from 'primevue/toasteventbus';
import ToastMessage from './ToastMessage.vue';
import {DomHandler} from 'primevue/utils';
import {ZIndexUtils} from 'primevue/utils';
var messageIdx = 0;
@ -55,10 +55,14 @@ export default {
this.messages = [];
});
this.updateZIndex();
if (this.autoZIndex) {
ZIndexUtils.set('modal', this.$refs.container, this.baseZIndex || this.$primevue.config.zIndex.modal);
}
},
beforeUpdate() {
this.updateZIndex();
beforeUnmount() {
if (this.$refs.container && this.autoZIndex) {
ZIndexUtils.clear(this.$refs.container);
}
},
methods: {
add(message) {
@ -78,11 +82,6 @@ export default {
}
this.messages.splice(index, 1);
},
updateZIndex() {
if (this.autoZIndex) {
this.$refs.container.style.zIndex = String(this.baseZIndex + DomHandler.generateZIndex());
}
}
},
components: {

View File

@ -1,6 +1,4 @@
import {UniqueComponentId} from 'primevue/utils';
import {DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler} from 'primevue/utils';
import {UniqueComponentId,DomHandler,ConnectedOverlayScrollHandler,ZIndexUtils} from 'primevue/utils';
function bindEvents(el) {
const modifiers = el.$_ptooltipModifiers;
@ -72,7 +70,6 @@ function show(el) {
let tooltipElement = create(el);
align(el);
DomHandler.fadeIn(tooltipElement, 250);
tooltipElement.style.zIndex = ++DomHandler.zindex;
window.addEventListener('resize', function onWindowResize() {
hide(el);
@ -80,11 +77,13 @@ function show(el) {
});
bindScrollListener(el);
ZIndexUtils.set('tooltip', tooltipElement, el.$_ptooltipZIndex);
}
function hide(el) {
remove(el);
unbindScrollListener(el);
ZIndexUtils.clear(el);
}
function getTooltipElement(el) {
@ -245,6 +244,7 @@ const Tooltip = {
let target = getTarget(el);
target.$_ptooltipModifiers = options.modifiers;
target.$_ptooltipValue = options.value;
target.$_ptooltipZIndex = options.instance.$primevue && options.instance.$primevue.config && options.instance.$primevue.config.zIndex.tooltip;
bindEvents(target);
},
unmounted(el) {
@ -256,6 +256,8 @@ const Tooltip = {
target.$_ptooltipScrollHandler.destroy();
target.$_ptooltipScrollHandler = null;
}
ZIndexUtils.clear(el);
},
updated(el, options) {
let target = getTarget(el);

View File

@ -23,7 +23,7 @@
<span class="p-treeselect-trigger-icon pi pi-chevron-down"></span>
</div>
<Teleport :to="appendTo">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave">
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
<div :ref="overlayRef" v-if="overlayVisible" @click="onOverlayClick" :class="['p-treeselect-panel p-component', panelClass]">
<slot name="header" :value="modelValue" :options="options"></slot>
<div class="p-treeselect-items-wrapper" :style="{'max-height': scrollHeight}">
@ -43,7 +43,7 @@
</template>
<script>
import {ConnectedOverlayScrollHandler,DomHandler} from 'primevue/utils';
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils';
import OverlayEventBus from 'primevue/overlayeventbus';
import Tree from 'primevue/tree';
import Ripple from 'primevue/ripple';
@ -121,7 +121,11 @@ export default {
this.scrollHandler.destroy();
this.scrollHandler = null;
}
this.overlay = null;
if (this.overlay) {
ZIndexUtils.clear(this.overlay);
this.overlay = null;
}
},
mounted() {
this.updateTreeState();
@ -204,8 +208,8 @@ export default {
break;
}
},
onOverlayEnter() {
this.overlay.style.zIndex = String(DomHandler.generateZIndex());
onOverlayEnter(el) {
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
this.alignOverlay();
this.bindOutsideClickListener();
this.bindScrollListener();
@ -219,6 +223,9 @@ export default {
this.$emit('hide');
this.overlay = null;
},
onOverlayAfterLeave(el) {
ZIndexUtils.clear(el);
},
alignOverlay() {
this.overlay.style.minWidth = DomHandler.getOuterWidth(this.$el) + 'px';
DomHandler.absolutePosition(this.overlay, this.$el);

View File

@ -93,15 +93,6 @@ export default class DomHandler {
};
}
static generateZIndex() {
this.zindex = this.zindex||999;
return ++this.zindex;
}
static getCurrentZIndex() {
return this.zindex;
}
static index(element) {
let children = element.parentNode.childNodes;
let num = 0;

View File

@ -1,7 +1,8 @@
import ConnectedOverlayScrollHandler from './ConnectedOverlayScrollHandler';
import DomHandler from './DomHandler';
import ObjectUtils from './ObjectUtils';
import ZIndexUtils from './ZIndexUtils';
import UniqueComponentId from './UniqueComponentId';
import EventBus from './EventBus';
export {ConnectedOverlayScrollHandler,DomHandler,ObjectUtils,UniqueComponentId,EventBus};
export {ConnectedOverlayScrollHandler,DomHandler,ObjectUtils,ZIndexUtils,UniqueComponentId,EventBus};

View File

@ -0,0 +1,41 @@
function handler() {
let zIndexes = [];
const generateZIndex = (key, baseZIndex) => {
let lastZIndex = zIndexes.length > 0 ? zIndexes[zIndexes.length - 1] : { key, value: baseZIndex };
let newZIndex = lastZIndex.value + (lastZIndex.key === key ? 0 : baseZIndex) + 1;
zIndexes.push({ key, value: newZIndex });
return newZIndex;
}
const revertZIndex = (zIndex) => {
zIndexes = zIndexes.filter(obj => obj.value !== zIndex);
}
const getCurrentZIndex = () => {
return zIndexes.length > 0 ? zIndexes[zIndexes.length - 1].value : 0;
}
const getZIndex = (el) => {
return el ? parseInt(el.style.zIndex, 10) || 0 : 0
}
return {
get: getZIndex,
set: (key, el, baseZIndex) => {
if (el) {
el.style.zIndex = String(generateZIndex(key, baseZIndex));
}
},
clear: (el) => {
if (el) {
revertZIndex(getZIndex(el));
el.style.zIndex = '';
}
},
getCurrent: () => getCurrentZIndex()
};
}
export default handler();

View File

@ -220,6 +220,25 @@ app.use(PrimeVue, {ripple: true});
</code></pre>
<h5>ZIndex Layering</h5>
<p>ZIndexes are managed automatically to make sure layering of overlay components work seamlessly when combining multiple components. Still there may be cases where you'd like to configure
the configure default values such as a custom layout where header section is fixed. In a case like this, dropdown needs to be displayed below the application header but a modal dialog should be displayed above. PrimeVue configuration
offers the <i>zIndex</i> property to customize the default values for components categories. Default values are described below and can be customized when setting up PrimeVue.</p>
<pre v-code.script><code>
import {createApp} from 'vue';
import PrimeVue from 'primevue/config';
const app = createApp(App);
app.use(PrimeVue, {
zIndex: {
modal: 1100, //dialog, sidebar
overlay: 1000, //dropdown, overlaypanel
menu: 1000, //overlay menus
tooltip: 1100 //tooltip
}
});
</code></pre>
<h5>Locale</h5>
<p>PrimeVue provides a Locale API to support i18n and l7n, visit the <router-link to="/locale">Locale</router-link> documentation for more information.</p>