2020-12-26 15:03:12 +01:00
|
|
|
<template>
|
|
|
|
<div class="dropdown-container" ref="container">
|
2021-01-05 00:50:24 +01:00
|
|
|
<button :title="title" ref="button" @click.stop="toggle($event)">
|
2020-12-26 15:03:12 +01:00
|
|
|
<i class="icon" :class="iconClass" v-if="iconClass" />
|
|
|
|
<span class="text" v-text="text" v-if="text" />
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<div class="dropdown fade-in" :id="id" :class="{hidden: !visible}" ref="dropdown">
|
|
|
|
<slot />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
export default {
|
|
|
|
name: "Dropdown",
|
|
|
|
emits: ['click'],
|
|
|
|
props: {
|
|
|
|
id: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
|
|
|
|
items: {
|
|
|
|
type: Array,
|
|
|
|
default: () => [],
|
|
|
|
},
|
|
|
|
|
|
|
|
iconClass: {
|
|
|
|
type: String,
|
2021-01-14 00:15:35 +01:00
|
|
|
default: 'fa fa-ellipsis-h',
|
2020-12-26 15:03:12 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
text: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
|
|
|
|
title: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
visible: false,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
documentClickHndl(event) {
|
|
|
|
if (!this.visible)
|
|
|
|
return
|
|
|
|
|
|
|
|
let element = event.target
|
|
|
|
while (element) {
|
2021-01-18 01:28:10 +01:00
|
|
|
if (!this.$refs.dropdown)
|
|
|
|
break
|
|
|
|
if (element === this.$refs.dropdown.element)
|
2020-12-26 15:03:12 +01:00
|
|
|
return
|
|
|
|
|
|
|
|
element = element.parentElement
|
|
|
|
}
|
|
|
|
|
|
|
|
this.close()
|
|
|
|
},
|
|
|
|
|
|
|
|
close() {
|
|
|
|
this.visible = false
|
|
|
|
document.removeEventListener('click', this.documentClickHndl)
|
|
|
|
},
|
|
|
|
|
|
|
|
open() {
|
|
|
|
document.addEventListener('click', this.documentClickHndl)
|
|
|
|
this.visible = true
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
const element = this.$refs.dropdown
|
|
|
|
element.style.left = 0
|
|
|
|
element.style.top = parseFloat(getComputedStyle(this.$refs.button).height) + 'px'
|
|
|
|
|
2020-12-31 01:36:02 +01:00
|
|
|
if (element.getBoundingClientRect().left > window.innerWidth/2)
|
|
|
|
element.style.left = (-element.clientWidth + parseFloat(getComputedStyle(this.$refs.button).width)) + 'px'
|
2020-12-26 15:03:12 +01:00
|
|
|
|
2020-12-31 01:36:02 +01:00
|
|
|
if (element.getBoundingClientRect().top > window.innerHeight/2)
|
|
|
|
element.style.top = (-element.clientHeight + parseFloat(getComputedStyle(this.$refs.button).height)) + 'px'
|
2020-12-26 15:03:12 +01:00
|
|
|
}, 10)
|
|
|
|
},
|
|
|
|
|
2021-01-05 00:50:24 +01:00
|
|
|
toggle(event) {
|
|
|
|
event.stopPropagation()
|
|
|
|
this.$emit('click')
|
2020-12-26 15:03:12 +01:00
|
|
|
this.visible ? this.close() : this.open()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.dropdown-container {
|
|
|
|
position: relative;
|
2022-03-30 01:43:59 +02:00
|
|
|
display: inline-flex;
|
2020-12-26 15:03:12 +01:00
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
.dropdown {
|
|
|
|
position: absolute;
|
|
|
|
width: max-content;
|
|
|
|
background: $dropdown-bg;
|
|
|
|
border-radius: .25em;
|
|
|
|
border: $default-border-3;
|
|
|
|
box-shadow: $dropdown-shadow;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
z-index: 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|