Source: components/PromptLink/PromptLink.js

import document from 'global/document';

import { promptLink as promptLinkClassName } from './style.scss';
import renderTemplate from './template.pug';

/** 
 * Controla o mini modal de links da HandTalk, oculta e exibe uma caixa com a opção 'Acessar link'
 * abaixo de um link target link, ou seja, no link que foi clicado. 
*/
class PromptLink {
  ht = null;
  elem = null;
  a = null;

  static targetMarginHorizontal = -10;
  static targetMarginVertical = 45;
  static timerModal = 2000;
  
  constructor(ht) {
    this.ht = ht;

    this.elem = document.createElement('div');
    this.elem.classList.add(promptLinkClassName);
    this.elem.classList.add('ht-skip');
    this.elem.innerHTML = renderTemplate();
    this.ht.config.parentElement.appendChild(this.elem);

    this.a = this.elem.querySelector('.ht-pl-link');
  }

  /** Exibe o Prompt link abaixo de um elemento na tela
   * @param {target} - Elemento do tipo <a> para ser utilizado como base
   */
  showAt = (target, mouseX, mouseY) => {
    if (this.hasValidHrefContent(target)) {
      this.clearAttributes(this.a);
      this.cloneAttributes(target, this.a);
      this.calculatePosition(this.elem, mouseX, mouseY);
      this.visible = true;
      this.ht.on('signalized', () => {
        setTimeout(() => {
          this.hide();
        }, PromptLink.timerModal);
      });
    } else
      this.hide();
  }

  /**
   * Verifica se um elemento possui href e, se o mesmo é diferente de '' e de '#'
   * @param {element} - DOMElement a ser verificado
   */
  hasValidHrefContent = (element) => {
    if (!element.hasAttribute('href')) return false;

    const hrefContent = element.getAttribute('href');
    if (hrefContent == '') return false;
    if (hrefContent == '#') return false;

    return true;
  }

  /** Remove os atributos anteriormente clonados
   * @param {element} - Elemento que terá os atributos limpos 
   */
  clearAttributes = (element) => {
    if (element.hasAttribute('href')) element.removeAttribute('href');
    if (element.hasAttribute('target')) element.removeAttribute('target');
  }

  /** Clona os atributos de um elemento
   * @param {fromElement} - Elemento do qual os atributos serão copiados
   * @param {toElement} - Elemento do qual os atributos serão colados
   */
  cloneAttributes = (fromElement, toElement) => {
    if (fromElement.hasAttribute('href')) toElement.setAttribute('href', fromElement.getAttribute('href'));
    if (fromElement.hasAttribute('target')) toElement.setAttribute('target', fromElement.getAttribute('target'));
  }

  /** Seta a nova posição do prompt link na tela
   * @param {main} - Elemento que terá a posição alterada
   * @param {mouseX} - Coordenada X do mouse na tela.
   * @param {mouseY} - Coordenada Y do mouse na tela.
   */
  calculatePosition = (main, mouseX, mouseY) => {
    main.style.left = (mouseX + PromptLink.targetMarginHorizontal + window.pageXOffset) + 'px';
    main.style.top = (mouseY + PromptLink.targetMarginVertical + window.pageYOffset) + 'px';
  }

  /** Oculta o prompt link caso não esteja visivel */
  hide = () => { if (this.visible) this.visible = false; }

  _isVisible = false;
  get visible() { return this._isVisible; }
  set visible(value) {
    this._isVisible = value;
    if (this._isVisible) {
      this.elem.classList.remove('ht-pl-hide');
      this.elem.classList.add('ht-pl-show');
    } else {
      this.elem.classList.remove('ht-pl-show');
      this.elem.classList.add('ht-pl-hide');
    }
  }
}

export default PromptLink;