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.
217 lines
7.2 KiB
217 lines
7.2 KiB
<template>
|
|
<div>
|
|
<slot name="reference"/>
|
|
<transition :name="transition" @after-enter="handleAfterEnter" @after-leave="handleAfterLeave">
|
|
<div
|
|
ref="popper"
|
|
v-show="!disabled && showPopper"
|
|
class="el-popover el-popper"
|
|
:class="[popperClass, content && 'el-popover--plain']"
|
|
:style="{ width: width + 'px' }"
|
|
:id="tooltipId"
|
|
>
|
|
<div class="el-popover__title" v-if="title">
|
|
<slot name="title">{{title}}</slot>
|
|
</div>
|
|
<slot>{{ content }}</slot>
|
|
</div>
|
|
</transition>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import Popper from '@ele/mixins/vue-popper'
|
|
import {on, off} from 'element-ui/lib/utils/dom'
|
|
import {addClass, removeClass} from 'element-ui/lib/utils/dom'
|
|
import {generateId} from 'element-ui/lib/utils/util'
|
|
|
|
export default {
|
|
name: "ElPopover",
|
|
|
|
mixins: [Popper],
|
|
|
|
props: {
|
|
trigger: {
|
|
type: String,
|
|
default: 'click',
|
|
validator: value => ['click', 'focus', 'hover', 'manual'].indexOf(value) > -1
|
|
},
|
|
openDelay: {type: Number, default: 0},
|
|
closeDelay: {type: Number, default: 200},
|
|
transition: {type: String, default: 'fade-in-liner'},
|
|
popperClass: String,
|
|
title: String,
|
|
disabled: Boolean,
|
|
content: String,
|
|
width: {},
|
|
arrowOffset: {type: Number, default: 0}
|
|
},
|
|
|
|
data() {
|
|
return {}
|
|
},
|
|
|
|
computed: {
|
|
tooltipId() {
|
|
return `el-popover-${generateId()}`
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
showPopper(val) {
|
|
if (this.disabled) return
|
|
this.$emit(val ? 'show' : 'hide')
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
doToggle() {
|
|
this.showPopper = !this.showPopper
|
|
},
|
|
|
|
doShow() {
|
|
this.showPopper = true
|
|
},
|
|
|
|
doClose() {
|
|
this.showPopper = false
|
|
},
|
|
|
|
handleFocus() {
|
|
addClass(this.referenceElm, 'focusing')
|
|
if (this.trigger === 'click' || this.trigger === 'focus') this.showPopper = true
|
|
},
|
|
|
|
handleClick() {
|
|
removeClass(this.referenceElm, 'focusing')
|
|
},
|
|
|
|
handleBlur() {
|
|
removeClass(this.referenceElm, 'focusing')
|
|
if (this.trigger === 'click' || this.trigger === 'focus') this.showPopper = false
|
|
},
|
|
|
|
handleMouseEnter() {
|
|
window.clearTimeout(this._timer)
|
|
if (this.openDelay) {
|
|
this._timer = setTimeout(() => this.showPopper = true, this.openDelay)
|
|
}
|
|
else this.showPopper = true
|
|
},
|
|
|
|
handleKeydown(ev) {
|
|
if (ev.keyCode === 27 && this.trigger !== 'manual') { // esc
|
|
this.doClose()
|
|
}
|
|
},
|
|
|
|
handleMouseLeave() {
|
|
window.clearTimeout(this._timer)
|
|
if (this.closeDelay) {
|
|
this._timer = setTimeout(() => this.showPopper = false, this.closeDelay)
|
|
}
|
|
else this.showPopper = false
|
|
},
|
|
|
|
handleDocumentClick(e) {
|
|
let reference = this.reference || this.$refs.reference
|
|
const popper = this.popper || this.$refs.popper
|
|
|
|
if (!reference && this.$slots.reference && this.$slots.reference[0]) {
|
|
reference = this.referenceElm = this.$slots.reference[0].elm
|
|
}
|
|
if (!this.$el ||
|
|
!reference ||
|
|
this.$el.contains(e.target) ||
|
|
reference.contains(e.target) ||
|
|
!popper ||
|
|
popper.contains(e.target)) return
|
|
this.showPopper = false
|
|
},
|
|
|
|
handleAfterEnter() {
|
|
this.$emit('after-enter')
|
|
},
|
|
|
|
handleAfterLeave() {
|
|
this.$emit('after-leave')
|
|
this.doDestroy()
|
|
},
|
|
|
|
cleanup() {
|
|
if (this.openDelay || this.closeDelay) {
|
|
window.clearTimeout(this._timer)
|
|
}
|
|
}
|
|
},
|
|
|
|
mounted() {
|
|
let reference = this.referenceElm = this.reference || this.$refs.reference
|
|
const popper = this.popper || this.$refs.popper
|
|
|
|
if (!reference && this.$slots.reference && this.$slots.reference[0]) {
|
|
reference = this.referenceElm = this.$slots.reference[0].elm
|
|
}
|
|
|
|
if (reference) {
|
|
addClass(reference, 'el-popover__reference')
|
|
|
|
if (this.trigger !== 'click') {
|
|
on(reference, 'focusin', () => {
|
|
this.handleFocus()
|
|
const instance = reference.__vue__
|
|
if (instance && typeof instance.focus === 'function') {
|
|
instance.focus()
|
|
}
|
|
})
|
|
on(popper, 'focusin', this.handleFocus)
|
|
on(reference, 'focusout', this.handleBlur)
|
|
on(popper, 'focusout', this.handleBlur)
|
|
}
|
|
on(reference, 'keydown', this.handleKeydown)
|
|
on(reference, 'click', this.handleClick)
|
|
}
|
|
if (this.trigger === 'click') {
|
|
on(reference, 'click', this.doToggle)
|
|
on(document, 'click', this.handleDocumentClick)
|
|
}
|
|
else if (this.trigger === 'hover') {
|
|
on(reference, 'mouseenter', this.handleMouseEnter)
|
|
on(popper, 'mouseenter', this.handleMouseEnter)
|
|
on(reference, 'mouseleave', this.handleMouseLeave)
|
|
on(popper, 'mouseleave', this.handleMouseLeave)
|
|
}
|
|
else if (this.trigger === 'focus') {
|
|
if (reference.querySelector('input, textarea')) {
|
|
on(reference, 'focusin', this.doShow)
|
|
on(reference, 'focusout', this.doClose)
|
|
}
|
|
else {
|
|
on(reference, 'mousedown', this.doShow)
|
|
on(reference, 'mouseup', this.doClose)
|
|
}
|
|
}
|
|
},
|
|
|
|
beforeDestroy() {
|
|
this.cleanup()
|
|
|
|
const reference = this.reference
|
|
|
|
off(reference, 'click', this.doToggle)
|
|
off(reference, 'mouseup', this.doClose)
|
|
off(reference, 'mousedown', this.doShow)
|
|
off(reference, 'focusin', this.doShow)
|
|
off(reference, 'focusout', this.doClose)
|
|
off(reference, 'mousedown', this.doShow)
|
|
off(reference, 'mouseup', this.doClose)
|
|
off(reference, 'mouseleave', this.handleMouseLeave)
|
|
off(reference, 'mouseenter', this.handleMouseEnter)
|
|
off(document, 'click', this.handleDocumentClick)
|
|
},
|
|
|
|
deactivated() {
|
|
this.cleanup()
|
|
},
|
|
}
|
|
</script>
|
|
|