Skip to content

Commit

Permalink
feat: new handler props
Browse files Browse the repository at this point in the history
  • Loading branch information
oleksiikhr committed Aug 22, 2020
1 parent b410fff commit a64d090
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 42 deletions.
11 changes: 5 additions & 6 deletions demo/components/BaseHeader.vue
Expand Up @@ -2,6 +2,7 @@
<vsm-menu
ref="header"
:menu="menu"
:handler="handler"
:screen-offset="15"
@open-dropdown="onOpenDropdown"
@close-dropdown="onCloseDropdown"
Expand All @@ -28,7 +29,7 @@
class="vsm-section vsm-mob-hide rnd--open"
@click="onClick"
>
Random
on {{ handler }}
</li>
<!--Display mobile menu-->
<vsm-mob>
Expand All @@ -45,7 +46,6 @@ import VerticalContent from '../components/content/Vertical'
import DefaultContent from '../components/content/Default'
import StripeLogo from '../components/svg/StripeLogo'
import MobileContent from './content/MobileContent'
import rnd from '../sciprts/rnd'
/* eslint-disable no-console */
Expand All @@ -55,6 +55,7 @@ export default {
},
data () {
return {
handler: 'hover',
menu: [
{ title: 'Company', dropdown: 'company', content: DefaultContent, listeners: { mouseover: this.onMouseOver } },
{ title: 'Developers', dropdown: 'developers', content: HorizontalPrimaryContent, secondary: HorizontalSecondaryContent },
Expand All @@ -65,10 +66,8 @@ export default {
},
methods: {
onClick () {
const links = this.$refs.header.hasDropdownEls
const link = links[rnd(0, links.length - 1)]
this.$refs.header.openDropdown(link)
this.handler = this.handler === 'hover' ? 'click' : 'hover'
console.log(`Change Handler to ${this.handler}`)
},
onMouseOver (evt) {
console.log('mouse over', evt)
Expand Down
122 changes: 86 additions & 36 deletions src/components/Menu.vue
Expand Up @@ -141,6 +141,15 @@ export default {
type: [Number, String],
default: 10,
validator: (val) => +val >= 0
},
/**
* By default, the dropdown list drops out on hover,
* you can change this behavior on click
*/
handler: {
type: String,
default: 'hover',
validator: (val) => ['hover', 'click'].includes(val)
}
},
computed: {
Expand Down Expand Up @@ -180,6 +189,13 @@ export default {
}))
}
},
watch: {
handler (val) {
this.handler = val
this.registerDropdownElsEvents(true)
this.registerDropdownContainerEvents(true)
}
},
mounted () {
// PointerEvent interface represents the state of a DOM event
this._pointerEvent = window.PointerEvent ? {
Expand All @@ -206,63 +222,97 @@ export default {
document.addEventListener('touchstart', this.touchStartHandler)
document.body.addEventListener(this._pointerEvent.end, this.eventEndHandler)
},
registerDropdownElsEvents () {
registerDropdownElsEvents (force = false) {
this.hasDropdownEls.forEach((el) => {
// Events have been registered
if (el._vsm_menu) {
if (el._vsmMenu && !force) {
return
}
el.addEventListener('focusin', () => {
this.stopCloseTimeout()
this.openDropdown(el)
})
if (el._vsmMenuHandlers) {
Object.entries(el._vsmMenuHandlers).forEach(([eventName, fn]) => {
el.removeEventListener(eventName, fn)
})
}
el.addEventListener(this._pointerEvent.enter, (evt) => {
if (evt.pointerType !== 'touch') {
this.stopCloseTimeout()
this.openDropdown(el)
if (this.handler === 'hover') {
el._vsmMenuHandlers = {
focusin: () => {
this.stopCloseTimeout()
this.openDropdown(el)
},
[this._pointerEvent.enter]: (evt) => {
if (evt.pointerType !== 'touch') {
this.stopCloseTimeout()
this.openDropdown(el)
}
},
[this._pointerEvent.end]: (evt) => {
evt.preventDefault()
evt.stopPropagation()
this.toggleDropdown(el)
},
[this._pointerEvent.leave]: (evt) => {
if (evt.pointerType !== 'touch') {
this.startCloseTimeout()
}
}
}
})
el.addEventListener(this._pointerEvent.end, (evt) => {
evt.preventDefault()
evt.stopPropagation()
this.toggleDropdown(el)
})
el.addEventListener(this._pointerEvent.leave, (evt) => {
if (evt.pointerType !== 'touch') {
this.startCloseTimeout()
} else {
el._vsmMenuHandlers = {
click: () => {
this.toggleDropdown(el)
}
}
}
Object.entries(el._vsmMenuHandlers).forEach(([eventName, fn]) => {
el.addEventListener(eventName, fn)
})
el._vsm_menu = true
el._vsmMenu = true
})
},
registerDropdownContainerEvents () {
registerDropdownContainerEvents (force = false) {
const el = this.$refs.dropdownContainer
// Events have been registered
if (this.$refs.dropdownContainer._vsm_menu) {
if (el._vsmMenu && !force) {
return
}
this.$refs.dropdownContainer.addEventListener(this._pointerEvent.end, (evt) => {
evt.stopPropagation()
})
if (el._vsmMenuHandlers) {
Object.entries(el._vsmMenuHandlers).forEach(([eventName, fn]) => {
el.removeEventListener(eventName, fn)
})
}
this.$refs.dropdownContainer.addEventListener(this._pointerEvent.enter, (evt) => {
if (evt.pointerType !== 'touch') {
this.stopCloseTimeout()
if (this.handler === 'hover') {
el._vsmMenuHandlers = {
[this._pointerEvent.enter]: (evt) => {
if (evt.pointerType !== 'touch') {
this.stopCloseTimeout()
}
},
[this._pointerEvent.leave]: (evt) => {
if (evt.pointerType !== 'touch') {
this.startCloseTimeout()
}
}
}
})
} else {
el._vsmMenuHandlers = {}
}
this.$refs.dropdownContainer.addEventListener(this._pointerEvent.leave, (evt) => {
if (evt.pointerType !== 'touch') {
this.startCloseTimeout()
}
el._vsmMenuHandlers[this._pointerEvent.end] = (evt) => {
evt.stopPropagation()
}
Object.entries(el._vsmMenuHandlers).forEach(([eventName, fn]) => {
el.addEventListener(eventName, fn)
})
this.$refs.dropdownContainer._vsm_menu = true
el._vsmMenu = true
},
unregisterGlobalEvents () {
window.removeEventListener('resize', this.windowResizeHandler)
Expand Down

0 comments on commit a64d090

Please sign in to comment.