All files / app/assets/javascripts/tooltips index.js

98.14% Statements 53/54
66.66% Branches 10/15
95.23% Functions 20/21
100% Lines 46/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98            212x           212x 212x   212x 120x 16x   16x 16x   16x     16x                   120x     212x   212x 8x     212x 5x 5x 5x 5x         212x 56x   56x     1272x 56x     212x 9x 18x   9x 18x   5x         9x   212x 212x 212x 212x 1x   212x 1x   212x 44x   212x 1x   212x 212x 9x 9x    
import { toArray, isElement } from 'lodash';
import Vue from 'vue';
import Tooltips from './components/tooltips.vue';
 
let app;
 
const EVENTS_MAP = {
  hover: 'mouseenter',
  click: 'click',
  focus: 'focus',
};
 
const DEFAULT_TRIGGER = 'hover focus';
const APP_ELEMENT_ID = 'gl-tooltips-app';
 
const tooltipsApp = () => {
  if (!app) {
    const container = document.createElement('div');
 
    container.setAttribute('id', APP_ELEMENT_ID);
    document.body.appendChild(container);
 
    app = new Vue({
      name: 'TooltipsRoot',
      render(h) {
        return h(Tooltips, {
          props: {
            elements: this.elements,
          },
          ref: 'tooltips',
        });
      },
    }).$mount(container);
  }
 
  return app.$refs.tooltips;
};
 
const isTooltip = (node, selector) => node.matches && node.matches(selector);
 
const addTooltips = (elements, config) => {
  tooltipsApp().addTooltips(toArray(elements), config);
};
 
const handleTooltipEvent = (rootTarget, e, selector, config = {}) => {
  for (let { target } = e; target && target !== rootTarget; target = target.parentNode) {
    Eif (isTooltip(target, selector)) {
      addTooltips([target], config);
      break;
    }
  }
};
 
const applyToElements = (elements, handler) => {
  const iterable = isElement(elements) ? [elements] : toArray(elements);
 
  toArray(iterable).forEach(handler);
};
 
const createTooltipApiInvoker = (glHandler) => (elements) => {
  applyToElements(elements, glHandler);
};
 
export const initTooltips = (config = {}) => {
  const triggers = config?.triggers || DEFAULT_TRIGGER;
  const events = triggers.split(' ').map((trigger) => EVENTS_MAP[trigger]);
 
  events.forEach((event) => {
    document.addEventListener(
      event,
      (e) => handleTooltipEvent(document, e, config.selector, config),
      true,
    );
  });
 
  return tooltipsApp();
};
export const add = (elements, config = {}) => addTooltips(elements, config);
export const dispose = createTooltipApiInvoker((element) => tooltipsApp().dispose(element));
export const fixTitle = createTooltipApiInvoker((element) => tooltipsApp().fixTitle(element));
export const enable = createTooltipApiInvoker((element) =>
  tooltipsApp().triggerEvent(element, 'enable'),
);
export const disable = createTooltipApiInvoker((element) =>
  tooltipsApp().triggerEvent(element, 'disable'),
);
export const hide = createTooltipApiInvoker((element) =>
  tooltipsApp().triggerEvent(element, 'close'),
);
export const show = createTooltipApiInvoker((element) =>
  tooltipsApp().triggerEvent(element, 'open'),
);
export const once = (event, cb) => tooltipsApp().$once(event, cb);
export const destroy = () => {
  tooltipsApp().$destroy();
  app = null;
};