123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- import Vue from 'vue';
- import merge from 'element-ui/src/utils/merge';
- import PopupManager from 'element-ui/src/utils/popup/popup-manager';
- import getScrollBarWidth from '../scrollbar-width';
- let idSeed = 1;
- const transitions = [];
- const hookTransition = (transition) => {
- if (transitions.indexOf(transition) !== -1) return;
- const getVueInstance = (element) => {
- let instance = element.__vue__;
- if (!instance) {
- const textNode = element.previousSibling;
- if (textNode.__vue__) {
- instance = textNode.__vue__;
- }
- }
- return instance;
- };
- Vue.transition(transition, {
- afterEnter(el) {
- const instance = getVueInstance(el);
- if (instance) {
- instance.doAfterOpen && instance.doAfterOpen();
- }
- },
- afterLeave(el) {
- const instance = getVueInstance(el);
- if (instance) {
- instance.doAfterClose && instance.doAfterClose();
- }
- }
- });
- };
- 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
- },
- transition: {
- type: String,
- default: ''
- },
- 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
- }
- },
- created() {
- if (this.transition) {
- hookTransition(this.transition);
- }
- },
- beforeMount() {
- this._popupId = 'popup-' + idSeed++;
- PopupManager.register(this._popupId, this);
- },
- beforeDestroy() {
- PopupManager.deregister(this._popupId);
- PopupManager.closeModal(this._popupId);
- if (this.modal && this.bodyOverflow !== null && this.bodyOverflow !== 'hidden') {
- document.body.style.overflow = this.bodyOverflow;
- document.body.style.paddingRight = this.bodyPaddingRight;
- }
- this.bodyOverflow = null;
- this.bodyPaddingRight = null;
- },
- data() {
- return {
- opened: false,
- bodyOverflow: null,
- bodyPaddingRight: null,
- 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) {
- if (!this.bodyOverflow) {
- this.bodyPaddingRight = document.body.style.paddingRight;
- this.bodyOverflow = document.body.style.overflow;
- }
- scrollBarWidth = getScrollBarWidth();
- let bodyHasOverflow = document.documentElement.clientHeight < document.body.scrollHeight;
- if (scrollBarWidth > 0 && bodyHasOverflow) {
- document.body.style.paddingRight = scrollBarWidth + 'px';
- }
- document.body.style.overflow = 'hidden';
- }
- }
- if (getComputedStyle(dom).position === 'static') {
- dom.style.position = 'absolute';
- }
- dom.style.zIndex = PopupManager.nextZIndex();
- this.opened = true;
- this.onOpen && this.onOpen();
- if (!this.transition) {
- 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(() => {
- if (this.modal && this.bodyOverflow !== 'hidden') {
- document.body.style.overflow = this.bodyOverflow;
- document.body.style.paddingRight = this.bodyPaddingRight;
- }
- this.bodyOverflow = null;
- this.bodyPaddingRight = null;
- }, 200);
- }
- this.opened = false;
- if (!this.transition) {
- this.doAfterClose();
- }
- },
- doAfterClose() {
- PopupManager.closeModal(this._popupId);
- this._closing = false;
- }
- }
- };
- export {
- PopupManager
- };
|