click-outside icon indicating copy to clipboard operation
click-outside copied to clipboard

Does not work with IE11, but I have a fix

Open AndreasHeintze opened this issue 6 years ago • 0 comments

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.

AndreasHeintze avatar Nov 20 '18 15:11 AndreasHeintze