Skip to content

Commit

Permalink
feat(dropdown): make show/hide events cancelable . also adds toggle e…
Browse files Browse the repository at this point in the history
…vent (#1807)
  • Loading branch information
jacobmllr95 authored and pi0 committed May 17, 2018
1 parent 5a7a290 commit 4136bd9
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 20 deletions.
32 changes: 28 additions & 4 deletions src/components/dropdown/package.json
Expand Up @@ -11,23 +11,47 @@
"bDropdownDivider"
],
"events": [
{
"event": "show",
"description": "Emitted just before dropdown is shown. Cancelable.",
"args": [
{
"arg": "bvEvt",
"description": "BvEvent object. Call bvEvt.preventDefault() to cancel show."
}
]
},
{
"event": "shown",
"description": "Emitted When dropdown is shown"
"description": "Emitted when dropdown is shown."
},
{
"event": "hide",
"description": "Emitted just before dropdown is hidden. Cancelable.",
"args": [
{
"arg": "bvEvt",
"description": "BvEvent object. Call bvEvt.preventDefault() to cancel hide."
}
]
},
{
"event": "hidden",
"description": "Emitted When dropdown is hidden"
"description": "Emitted when dropdown is hidden."
},
{
"event": "toggle",
"description": "Emitted when toggle button is clicked."
},
{
"event": "click",
"description": "Emitted when split button clicked in split mode."
"description": "Emitted when split button is clicked in split mode."
}
],
"slots": [
{
"name": "button-content",
"description": "Can be used to implement custom text with icons and more styling"
"description": "Can be used to implement custom text with icons and more styling."
},
{
"name": "text",
Expand Down
58 changes: 42 additions & 16 deletions src/mixins/dropdown.js
Expand Up @@ -4,6 +4,7 @@ import listenOnRootMixin from './listen-on-root'
import { from as arrayFrom } from '../utils/array'
import { assign } from '../utils/object'
import KeyCodes from '../utils/key-codes'
import BvEvent from '../utils/bv-event.class'
import warn from '../utils/warn'
import { isVisible, closest, selectAll, getAttr, eventOn, eventOff } from '../utils/dom'

Expand Down Expand Up @@ -68,7 +69,8 @@ export default {
data () {
return {
visible: false,
inNavbar: null
inNavbar: null,
visibleChangePrevented: false
}
},
created () {
Expand Down Expand Up @@ -97,19 +99,36 @@ export default {
this.removePopper()
},
watch: {
visible (state, old) {
if (state === old) {
// Avoid duplicated emits
visible (newValue, oldValue) {
if (this.visibleChangePrevented) {
this.visibleChangePrevented = false
return
}
if (state) {
this.showMenu()
} else {
this.hideMenu()

if (newValue !== oldValue) {
const evtName = newValue ? 'show' : 'hide'
let bvEvt = new BvEvent(evtName, {
cancelable: true,
vueTarget: this,
target: this.$refs.menu,
relatedTarget: null
})
this.emitEvent(bvEvt)
if (bvEvt.defaultPrevented) {
// Reset value and exit if canceled
this.visibleChangePrevented = true
this.visible = oldValue
return
}
if (evtName === 'show') {
this.showMenu()
} else {
this.hideMenu()
}
}
},
disabled (state, old) {
if (state !== old && state && this.visible) {
disabled (newValue, oldValue) {
if (newValue !== oldValue && newValue && this.visible) {
// Hide dropdown if disabled changes to true
this.visible = false
}
Expand All @@ -121,12 +140,16 @@ export default {
}
},
methods: {
// Event emitter
emitEvent (bvEvt) {
const type = bvEvt.type
this.$emit(type, bvEvt)
this.emitOnRoot(`bv::dropdown::${type}`, bvEvt)
},
showMenu () {
if (this.disabled) {
return
}
// TODO: move emit show to visible watcher, to allow cancelling of show
this.$emit('show')
// Ensure other menus are closed
this.emitOnRoot('bv::dropdown::shown', this)

Expand Down Expand Up @@ -157,8 +180,6 @@ export default {
this.$nextTick(this.focusFirstItem)
},
hideMenu () {
// TODO: move emit hide to visible watcher, to allow cancelling of hide
this.$emit('hide')
this.setTouchStart(false)
this.emitOnRoot('bv::dropdown::hidden', this)
this.$emit('hidden')
Expand Down Expand Up @@ -258,12 +279,17 @@ export default {
// We only toggle on Click, Enter, Space, and Arrow Down
return
}
evt.preventDefault()
evt.stopPropagation()
if (this.disabled) {
this.visible = false
return
}
this.$emit('toggle', evt)
if (evt.defaultPrevented) {
// Exit if canceled
return
}
evt.preventDefault()
evt.stopPropagation()
// Toggle visibility
this.visible = !this.visible
},
Expand Down

0 comments on commit 4136bd9

Please sign in to comment.