@prettyy/ui
Version:
vue2 UI
218 lines (183 loc) • 5.25 kB
JavaScript
import Vue from 'vue'
import merge from "../merge"
import PopupManager from "./popup-manager"
import getScrollBarWidth from '../scrollbar-width'
import { getStyle, addClass, removeClass, hasClass } from "../dom"
let idSeed = 1
let scrollBarWidth
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 = 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
}