import Vue from 'vue'; import merge from 'element-ui/src/utils/merge'; import PopupManager from './popup-manager'; import getScrollBarWidth from 'element-ui/src/utils/scrollbar-width'; import { getStyle, addClass, removeClass, hasClass } from 'element-ui/src/utils/dom'; let idSeed = 1; let scrollBarWidth; const getDOM = function(dom) { if (dom.nodeType === 3) { dom = dom.nextElementSibling || dom.nextSibling; getDOM(dom); } return dom; }; export default { props: { visible: { type: Boolean, default: false }, openDelay: {}, closeDelay: {}, zIndex: {}, modal: { type: Boolean, default: false }, modalFade: { type: Boolean, default: true }, modalClass: {}, modalAppendToBody: { type: Boolean, default: false }, lockScroll: { type: Boolean, default: true }, closeOnPressEscape: { type: Boolean, default: false }, closeOnClickModal: { type: Boolean, default: false } }, beforeMount() { this._popupId = 'popup-' + idSeed++; PopupManager.register(this._popupId, this); }, beforeDestroy() { PopupManager.deregister(this._popupId); PopupManager.closeModal(this._popupId); this.restoreBodyStyle(); }, data() { return { opened: false, bodyPaddingRight: null, computedBodyPaddingRight: 0, withoutHiddenClass: true, rendered: false }; }, watch: { visible(val) { if (val) { if (this._opening) return; if (!this.rendered) { this.rendered = true; Vue.nextTick(() => { this.open(); }); } else { this.open(); } } else { this.close(); } } }, methods: { open(options) { if (!this.rendered) { this.rendered = true; } const props = merge({}, this.$props || this, options); if (this._closeTimer) { clearTimeout(this._closeTimer); this._closeTimer = null; } clearTimeout(this._openTimer); const openDelay = Number(props.openDelay); if (openDelay > 0) { this._openTimer = setTimeout(() => { this._openTimer = null; this.doOpen(props); }, openDelay); } else { this.doOpen(props); } }, doOpen(props) { if (this.$isServer) return; if (this.willOpen && !this.willOpen()) return; if (this.opened) return; this._opening = true; const dom = getDOM(this.$el); const modal = props.modal; const zIndex = props.zIndex; if (zIndex) { PopupManager.zIndex = zIndex; } if (modal) { if (this._closing) { PopupManager.closeModal(this._popupId); this._closing = false; } PopupManager.openModal(this._popupId, PopupManager.nextZIndex(), this.modalAppendToBody ? undefined : dom, props.modalClass, props.modalFade); if (props.lockScroll) { this.withoutHiddenClass = !hasClass(document.body, 'el-popup-parent--hidden'); if (this.withoutHiddenClass) { this.bodyPaddingRight = document.body.style.paddingRight; this.computedBodyPaddingRight = parseInt(getStyle(document.body, 'paddingRight'), 10); } scrollBarWidth = getScrollBarWidth(); let bodyHasOverflow = document.documentElement.clientHeight < document.body.scrollHeight; let bodyOverflowY = getStyle(document.body, 'overflowY'); if (scrollBarWidth > 0 && (bodyHasOverflow || bodyOverflowY === 'scroll') && this.withoutHiddenClass) { document.body.style.paddingRight = this.computedBodyPaddingRight + scrollBarWidth + 'px'; } addClass(document.body, 'el-popup-parent--hidden'); } } if (getComputedStyle(dom).position === 'static') { dom.style.position = 'absolute'; } dom.style.zIndex = PopupManager.nextZIndex(); this.opened = true; this.onOpen && this.onOpen(); this.doAfterOpen(); }, doAfterOpen() { this._opening = false; }, close() { if (this.willClose && !this.willClose()) return; if (this._openTimer !== null) { clearTimeout(this._openTimer); this._openTimer = null; } clearTimeout(this._closeTimer); const closeDelay = Number(this.closeDelay); if (closeDelay > 0) { this._closeTimer = setTimeout(() => { this._closeTimer = null; this.doClose(); }, closeDelay); } else { this.doClose(); } }, doClose() { this._closing = true; this.onClose && this.onClose(); if (this.lockScroll) { setTimeout(this.restoreBodyStyle, 200); } this.opened = false; this.doAfterClose(); }, doAfterClose() { PopupManager.closeModal(this._popupId); this._closing = false; }, restoreBodyStyle() { if (this.modal && this.withoutHiddenClass) { document.body.style.paddingRight = this.bodyPaddingRight; removeClass(document.body, 'el-popup-parent--hidden'); } this.withoutHiddenClass = true; } } }; export { PopupManager };