Skip to content

Does not work with IE11, but I have a fixΒ #15

@AndreasHeintze

Description

@AndreasHeintze

I noticed that this does not work in IE11, so I made some changes to make it work in IE11 too.
Here is the updated version.

function validate(binding) {
    if (typeof binding.value !== 'function') {
      // eslint-disable-next-line
      console.warn('[Vue-click-outside:] provided expression', binding.expression, 'is not a function.')
      return false
    }
  
    return true
  }
  
  function isPopup(popupItem, elements) {
    if (!popupItem || !elements)
      return false
  
    for (var i = 0, len = elements.length; i < len; i++) {
      try {
        if (popupItem.contains(elements[i])) {
          return true
        }
        if (elements[i].contains(popupItem)) {
          return false
        }
      } catch(e) {
        return false
      }
    }
  
    return false
  }
  
  function isServer(vNode) {
    return typeof vNode.componentInstance !== 'undefined' && vNode.componentInstance.$isServer
  }

  // Since IE11 doesn't support e.composedPath()
  function composedPath (el) {
    var path = []
    while (el) {
      path.push(el)
      if (el.tagName === 'HTML') {
        path.push(document)
        path.push(window)
        return path
      }
      el = el.parentNode
    }
  }

  exports = module.exports = {
    bind: function (el, binding, vNode) {
      if (!validate(binding)) return
  
      // Define Handler and cache it on the element
      function handler(e) {
        if (!vNode.context) return
  
        // some components may have related popup item, on which we shall prevent the click outside event handler.
        var elements = e.path || (e.composedPath && e.composedPath()) || composedPath(e.target)
        elements && elements.length > 0 && elements.unshift(e.target)

        if (el.contains(e.target) || isPopup(vNode.context.popupItem, elements)) return
  
        el.__vueClickOutside__.callback(e)
      }
  
      // add Event Listeners
      el.__vueClickOutside__ = {
        handler: handler,
        callback: binding.value
      }
      const clickHandler = 'ontouchstart' in document.documentElement ? 'touchstart' : 'click'
      !isServer(vNode) && document.addEventListener(clickHandler, handler)
    },
  
    update: function (el, binding) {
      if (validate(binding)) el.__vueClickOutside__.callback = binding.value
    },
    
    unbind: function (el, binding, vNode) {
      // Remove Event Listeners
      const clickHandler = 'ontouchstart' in document.documentElement ? 'touchstart' : 'click'
      !isServer(vNode) && document.removeEventListener(clickHandler, el.__vueClickOutside__.handler)
      delete el.__vueClickOutside__
    }
  }

Note! This does also contain the fix for IOS devices.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions