const isTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints > 0

const directive = {
  instances: [],
  events: isTouch ? ['touchstart', 'click'] : ['click']
}

directive.onEvent = function (event) {
  directive.instances.forEach(({ el, fn, mod }) => {
    if (event.type === 'touchstart' && mod.notouch) {
      return
    }
    if (event.target !== el && !el.contains(event.target)) {
      fn && fn(event)
    }
  })
}

directive.bind = function (el, binding) {
  directive.instances.push({ el, fn: binding.value, mod: binding.modifiers })
  if (directive.instances.length === 1) {
    directive.events.forEach(e => document.addEventListener(e, directive.onEvent))
  }
}

directive.update = function (el, binding) {
  if (typeof binding.value !== 'function') {
    throw new Error('Argument must be a function')
  }
  const instance = directive.instances.find(i => i.el === el)
  instance.fn = binding.value
}

directive.unbind = function (el) {
  const instanceIndex = directive.instances.findIndex(i => i.el === el)
  if (instanceIndex >= 0) {
    directive.instances.splice(instanceIndex, 1)
  }
  if (directive.instances.length === 0) {
    directive.events.forEach(e => document.removeEventListener(e, directive.onEvent))
  }
}

export default typeof window !== 'undefined' ? directive : {}

@@ -248,16 +248,24 @@
  fn, mod
+, userFn
  %7D) =%3E %7B
@@ -395,16 +395,37 @@
 .target)
+ && userFn(el, event)
 ) %7B%0A    
@@ -494,24 +494,180 @@
  binding) %7B%0A
+  const handler = typeof binding.value === 'function' ? binding.value : binding.value.handler%0A  const middleware = binding.value.middleware %7C%7C (() =%3E true)%0A
   directive.
@@ -691,29 +691,23 @@
 el, fn: 
-binding.value
+handler
 , mod: b
@@ -722,16 +722,36 @@
 odifiers
+, userFn: middleware
  %7D)%0A  if

Add middleware function to directive binding (#33)