click-outside.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /* eslint-disable */
  2. // https://github.com/simplesmiler/vue-clickaway
  3. // https://github.com/ndelvalle/v-click-outside/blob/master/lib/v-click-outside.js
  4. // Mixed both :)
  5. const EVENTS = ['click'];
  6. const instances = [];
  7. const ClickOutside = {
  8. instances,
  9. beforeMount: bind,
  10. update: (el, binding) => {
  11. if (JSON.stringify(binding.value) === JSON.stringify(binding.oldValue))
  12. return;
  13. bind(el, binding);
  14. },
  15. unmounted: unbind,
  16. };
  17. function bind(el, { value }) {
  18. unbind(el);
  19. const bindingValue = value;
  20. const isFunction = typeof bindingValue === 'function';
  21. const isObject = typeof bindingValue === 'object';
  22. if (!isFunction && !isObject)
  23. return;
  24. const isActive = !(bindingValue.isActive === false);
  25. if (!isActive)
  26. return;
  27. const handler = isFunction ? bindingValue : bindingValue.handler;
  28. const instance = createInstance({ el, handler });
  29. instance.eventHandlers.forEach(({ event, handler }) => setTimeout(() => document.addEventListener(event, handler, false), 0));
  30. instances.push(instance);
  31. }
  32. function unbind(el) {
  33. const instanceIndex = instances.findIndex((instance) => instance.el === el);
  34. if (instanceIndex === -1)
  35. return;
  36. const instance = instances[instanceIndex];
  37. instance.eventHandlers.forEach(({ event, handler }) => document.removeEventListener(event, handler, false));
  38. instances.splice(instanceIndex, 1);
  39. }
  40. // --------------------
  41. // Helpers
  42. // --------------------
  43. function createInstance({ el, handler }) {
  44. return {
  45. el,
  46. eventHandlers: EVENTS.map((eventName) => ({
  47. event: eventName,
  48. handler: (event) => onEvent({ event, el, handler }),
  49. })),
  50. };
  51. }
  52. function onEvent({ event, el, handler }) {
  53. const path = event.path || (event.composedPath ? event.composedPath() : undefined);
  54. if (path ? path.indexOf(el) < 0 : !el.contains(event.target)) {
  55. return handler && handler(event, el);
  56. }
  57. }
  58. export default ClickOutside;