|
|
|
|
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() : this.destroyPopper()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|