Skip to content

Instantly share code, notes, and snippets.

@LeandrodeLimaC
Last active March 9, 2024 02:36
Show Gist options
  • Save LeandrodeLimaC/76f5fed3bd54397d073be5ff14086669 to your computer and use it in GitHub Desktop.
Save LeandrodeLimaC/76f5fed3bd54397d073be5ff14086669 to your computer and use it in GitHub Desktop.
Vue directive click outside element
// @ts-nocheck
import Vue from 'vue'
const events = ['click', 'touchstart', 'scroll']
function onClickOutside ({ event, el, handler }) {
const isClickOutside = event.target !== el && !el.contains(event.target)
if (!isClickOutside) { return null }
return handler(event, el)
}
const instances = new Map()
function toggleEventListeners (eventHandlers) {
return (action) => {
eventHandlers.forEach(({ event, handler }) => {
document[`${action}EventListener`](event, handler, true)
})
}
}
// Validator function
function processArgs (value) {
const isFunction = typeof value === 'function'
if (!isFunction) {
throw new Error(`v-click-outside: Binding value should be a function, ${typeof bindingValue} given`)
}
return {
handler: value
}
}
function eventAdapter (events, { el, handler }) {
return events.map(eventName => ({
event: eventName,
handler: event => onClickOutside({ event, el, handler })
}))
}
function bind (el, { value }) {
const { handler } = processArgs(value)
const eventHandlers = eventAdapter(events, { el, handler })
instances.set(
el,
eventHandlers
)
toggleEventListeners(eventHandlers)('add')
}
function unbind (el) {
const eventHandlers = instances.get(el)
toggleEventListeners(eventHandlers)('remove')
instances.delete(el)
}
Vue.directive('click-outside', { bind, unbind })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment