You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
5.5 KiB

import {PopupManager} from 'element-ui/lib/utils/popup'
import PopperJS from 'popper.js'
//import * as PopperJS from '@popperjs/core'
const POPPER_VERSION = 'v1'
if (POPPER_VERSION === 'v2') {
console.warn = () => ({})
}
const stop = e => e.stopPropagation()
const defaultOptions = () => {
return POPPER_VERSION === 'v2' ? {modifiers: []} : {modifiers: {computeStyle: {gpuAcceleration: false}}}
}
export default {
props: {
transformOrigin: {type: [Boolean, String], default: true},
placement: {type: String, default: 'bottom'},
boundariesPadding: {type: Number, default: 5},
reference: {},
popper: {},
offset: {type: Number, default: POPPER_VERSION === 'v2' ? 12 : 0},
value: Boolean,
visibleArrow: {type: Boolean, default: true},
arrowOffset: {type: Number, default: 35},
appendToBody: {type: Boolean, default: true},
popperOptions: {type: Object, default: defaultOptions}
},
data() {
return {
showPopper: this.value
}
},
watch: {
value: {
immediate: true,
handler(val) {
this.showPopper = val
this.$emit('input', val)
if (this.disabled) return
val && this.updatePopper()
}
}
},
methods: {
createPopper() {
if (!/^(top|bottom|left|right)(-start|-end)?$/g.test(this.placement)) {
return
}
const options = this.popperOptions
const popper = this.popperElm = this.popperElm || this.popper || this.$refs.popper
let reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference
if (!reference && this.$slots.reference && this.$slots.reference[0]) {
reference = this.referenceElm = this.$slots.reference[0].elm
}
if (!popper || !reference) return
if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) {
this.popperJS.destroy()
}
if (this.appendToBody) document.body.appendChild(this.popperElm)
if (this.visibleArrow) this.setArrow()
this.setOffset(options)
options.placement = this.placement
const createEvent = POPPER_VERSION === 'v2' ? 'onFirstUpdate' : 'onCreate'
options[createEvent] = () => {
this.$emit('created', this)
this.resetTransformOrigin()
this.$nextTick(this.updatePopper)
}
this.popperJS = POPPER_VERSION === 'v2' ?
PopperJS.createPopper(reference, popper, options)
: new PopperJS(reference, popper, options)
popper.style.zIndex = PopupManager.nextZIndex()
this.popperElm.addEventListener('click', stop)
},
updatePopper() {
const popper = this.popperJS
if (!popper) return this.createPopper()
popper.update()
this.popperElm.style.zIndex = PopupManager.nextZIndex()
},
doDestroy(forceDestroy) {
if (!this.popperJS || (this.showPopper && !forceDestroy)) return
this.popperJS.destroy()
this.popperJS = null
},
destroyPopper() {
this.popperJS && this.resetTransformOrigin()
},
setOffset(options) {
if (POPPER_VERSION === 'v2') {
const modifier = this.popperOptions.modifiers.find(modifier => modifier.name === 'offset'),
offset = {offset: [0, this.offset]}
if (!modifier) {
this.popperOptions.modifiers.push({name: 'offset', options: offset})
}
else modifier.options = offset
}
else {
if (!options.modifiers.offset) {
options.modifiers.offset = {}
}
options.modifiers.offset.offset = this.offset
}
},
setArrow() {
if (this.appended) return
this.appended = true
const arrow = document.createElement('div')
arrow.className = 'popper__arrow'
arrow.setAttribute(POPPER_VERSION === 'v2' ? 'data-popper-arrow' : 'x-arrow', '')
const attributes = this.popperElm.attributes
const key = Object.keys(attributes).find(key => /^_v-/.test(attributes[key].name))
if (key) arrow.setAttribute(attributes[key].name, '')
this.popperElm.appendChild(arrow)
},
resetTransformOrigin() {
if (!this.transformOrigin) return
const placementMap = {top: 'bottom', bottom: 'top', left: 'right', right: 'left'}
const attr = POPPER_VERSION === 'v2' ? 'data-popper-placement' : 'x-placement'
const placement = this.popperElm.getAttribute(attr).split('-')[0]
const origin = placementMap[placement]
this.popperElm.style.transformOrigin =
typeof this.transformOrigin === 'string'
? this.transformOrigin
: ['top', 'bottom'].includes(placement) ? `center ${origin}` : `${origin} center`
}
},
deactivated() {
this.$options.beforeDestroy[0].call(this)
},
beforeDestroy() {
this.doDestroy(true)
if (this.popperElm && this.popperElm.parentNode === document.body) {
this.popperElm.removeEventListener('click', stop)
document.body.removeChild(this.popperElm)
}
}
}