mand-mobile/components/drop-menu/index.vue

260 lines
6.2 KiB
Vue
Raw Normal View History

2018-03-26 16:04:04 +08:00
<template>
<div class="md-drop-menu">
<div class="md-drop-menu-bar">
2018-04-20 17:07:27 +08:00
<template v-for="(item, index) in data">
2018-03-26 16:04:04 +08:00
<div
class="bar-item"
:class="{
active: index === activeMenuBarIndex,
selected: $_checkBarItemSelect(index),
disabled: item.disabled
}"
:key="index"
@click="$_onBarItemClick(item, index)"
>
2018-04-20 17:07:27 +08:00
<span
2018-03-26 16:04:04 +08:00
v-text="$_getBarItemText(item, index)"
></span>
</div>
</template>
</div>
<md-popup
v-model="isPopupShow"
position="top"
prevent-scroll
:prevent-scroll-exclude="scroller"
2018-03-26 16:04:04 +08:00
@show="$_onListShow"
@hide="$_onListHide"
2018-08-14 14:54:22 +08:00
@before-hide="$_onListBeforeHide"
2018-03-26 16:04:04 +08:00
>
<div class="md-drop-menu-list">
2018-09-22 14:57:29 +08:00
<md-radio-list
2018-03-26 16:04:04 +08:00
v-model="selectedMenuListValue[activeMenuBarIndex]"
:options="activeMenuListData"
:is-slot-scope="hasSlot"
2018-09-22 14:57:29 +08:00
align-center
2018-03-26 16:04:04 +08:00
@change="$_onListItemClick"
>
<div slot-scope="{ option }">
<slot :option="option"></slot>
</div>
2018-09-22 14:57:29 +08:00
</md-radio-list>
2018-03-26 16:04:04 +08:00
</div>
</md-popup>
</div>
</template>
<script> import Popup from '../popup'
2018-09-22 14:57:29 +08:00
import RadioList from '../radio-list'
import {traverse, compareObjects} from '../_util'
2018-03-26 16:04:04 +08:00
export default {
name: 'md-drop-menu',
components: {
[Popup.name]: Popup,
2018-09-22 14:57:29 +08:00
[RadioList.name]: RadioList,
2018-03-26 16:04:04 +08:00
},
props: {
data: {
type: Array,
default() {
/* istanbul ignore next */
2018-03-26 16:04:04 +08:00
return []
},
},
defaultValue: {
type: Array,
default() {
return []
},
},
},
data() {
return {
isPopupShow: false,
selectedMenuListItem: [],
selectedMenuListValue: [],
selectedMenuListIndex: [],
activeMenuBarIndex: -1,
scroller: '',
2018-03-26 16:04:04 +08:00
}
},
computed: {
hasSlot() {
return !!this.$scopedSlots.default
},
2018-09-23 11:20:39 +08:00
activeMenuListData() {
if (this.activeMenuBarIndex < 0 || !this.data[this.activeMenuBarIndex]) {
2018-09-23 11:20:39 +08:00
return []
}
return this.data[this.activeMenuBarIndex].options
},
2018-03-26 16:04:04 +08:00
},
watch: {
data(val, oldVal) {
// Avoid Literals
/* istanbul ignore if */
if (!compareObjects(val, oldVal)) {
this.$_initSelectedBar()
}
},
defaultValue(val, oldVal) {
/* istanbul ignore if */
if (!compareObjects(val, oldVal)) {
this.$_initSelectedBar()
}
},
},
mounted() {
this.$_initSelectedBar()
},
methods: {
// MARK: private methods
$_initSelectedBar() {
this.selectedMenuListValue = this.defaultValue
traverse(this.data, ['options'], (item, level, indexs) => {
const barItemIndex = indexs[0]
const defaultValue = this.defaultValue[barItemIndex]
if (
defaultValue !== undefined &&
(item.value === defaultValue || item.text === defaultValue || item.label === defaultValue)
) {
this.$set(this.selectedMenuListItem, barItemIndex, item)
return 2
}
})
},
$_checkBarItemSelect(index) {
return !!(this.selectedMenuListItem[index] !== undefined || this.defaultValue[index])
},
$_getBarItemText(item, index) {
return this.selectedMenuListItem[index] !== undefined ? this.selectedMenuListItem[index].text : item.text
},
$_setScroller() {
const boxer = this.$el ? this.$el.querySelector('.md-popup-box') : null
/* istanbul ignore else */
if (boxer && boxer.clientHeight >= this.$el.clientHeight) {
2018-09-28 17:45:32 +08:00
this.scroller = '.md-drop-menu-list'
} else {
return ''
}
},
2018-03-26 16:04:04 +08:00
// MARK: events handler
$_onBarItemClick(barItem, index) {
/* istanbul ignore if */
if (!barItem || barItem.disabled) {
return
}
if (!this.isPopupShow) {
this.isPopupShow = true
this.activeMenuBarIndex = index
} else {
this.isPopupShow = false
}
},
$_onListItemClick(listItem) {
const activeMenuBarIndex = this.activeMenuBarIndex
const barItem = this.data[activeMenuBarIndex]
this.isPopupShow = false
2018-09-23 11:20:39 +08:00
this.selectedMenuListValue[activeMenuBarIndex] = listItem.value
2018-03-26 16:04:04 +08:00
this.$set(this.selectedMenuListItem, activeMenuBarIndex, listItem)
this.$emit('change', barItem, listItem)
},
$_onListShow() {
/* istanbul ignore next */
this.$_setScroller()
2018-03-26 16:04:04 +08:00
this.$emit('show')
},
$_onListHide() {
2018-09-28 17:45:32 +08:00
/* istanbul ignore next */
this.$emit('hide')
2018-08-14 14:54:22 +08:00
},
$_onListBeforeHide() {
/* istanbul ignore next */
this.activeMenuBarIndex = -1
},
2018-03-26 16:04:04 +08:00
// MARK: public methods
getSelectedValues() {
return this.selectedMenuListItem
},
getSelectedValue(index) {
return this.selectedMenuListItem[index]
},
},
}
</script>
<style lang="stylus">
.md-drop-menu
position fixed
z-index drop-menu-zindex
top 0
left 0
right 0
height drop-menu-height
box-sizing border-box
color color-text-minor
font-size drop-menu-font-size
2018-08-14 14:54:22 +08:00
font-weight drop-menu-font-weight
2018-09-03 17:28:32 +08:00
.md-drop-menu-bar
2018-09-23 11:20:39 +08:00
position relative
2018-09-03 17:28:32 +08:00
z-index drop-menu-zindex
display flex
height 100%
background drop-menu-bar-bg
hairline(bottom, drop-menu-bar-border-color)
.bar-item
2018-03-26 16:04:04 +08:00
display flex
2018-09-03 17:28:32 +08:00
flex 1
margin 2% 0
align-items center
justify-content center
span
position relative
padding-right 30px
&:after
content ""
position absolute
right 0
top 50%
width 0
height 0
margin-top -4px
border-left solid 8px transparent
border-right solid 8px transparent
border-top solid 9px color-border-element
2018-09-03 17:28:32 +08:00
transition transform .3s ease-in-out-quint
&.active
color drop-menu-color
2018-09-03 17:28:32 +08:00
span:after
transform rotate(180deg)
border-top-color drop-menu-color
2018-09-03 17:28:32 +08:00
&.selected
color drop-menu-color
&.disabled
opacity drop-menu-disabled-opacity
.md-drop-menu-list
width 100%
padding-top drop-menu-height
background drop-menu-list-bg
box-sizing border-box
.md-radio-item
font-weight font-weight-normal
&.is-selected .md-cell-item-title
color color-primary
2018-03-26 16:04:04 +08:00
</style>