Source: components/pomo-info/pomo-info.js

/**
 * @module PomoInfo
 */

class PomoInfo extends HTMLElement {
  constructor() {
    super();

    const shadow = this.attachShadow({ mode: 'open' });

    // event listener for opening info page
    this.openEvent = new CustomEvent('openEvent', {
      bubbles: true,
      composed: true,
    });

    // event listener for closing info page
    this.closeEvent = new CustomEvent('closeEvent', {
      bubbles: true,
      composed: true,
    });

    // value of accessibility
    this.accessible = true;

    // wrapper for element
    const wrapper = document.createElement('div');

    // style element for the component
    const infoStyle = document.createElement('link');
    infoStyle.setAttribute('id', 'info-styles');
    infoStyle.setAttribute('rel', 'stylesheet');
    infoStyle.setAttribute('href', './components/pomo-info/pomo-info.css');
    shadow.append(infoStyle);

    // the modal window
    const modal = document.createElement('div');
    modal.setAttribute('class', 'modal');
    modal.setAttribute('id', 'info-modal');
    modal.style.display = 'none';
    modal.onclick = (event) => {
      // close lightbox when click outside of the content area
      if (event.target === modal) {
        modal.style.display = 'none';
        shadow.dispatchEvent(this.closeEvent);
      }
    };

    // info button
    const infoButton = document.createElement('button');
    infoButton.setAttribute('id', 'info-button');

    const infoIcon = document.createElement('img');
    infoIcon.setAttribute('id', 'info-button-icon');
    infoIcon.setAttribute('src', './assets/images/i_info.png');
    infoIcon.textContent = 'Info';

    infoButton.appendChild(infoIcon);

    infoButton.onclick = () => {
      modal.style.display = 'block';
      shadow.dispatchEvent(this.openEvent);
    };

    // button to close the modal window
    const closeButton = document.createElement('div');
    closeButton.setAttribute('class', 'close-button');
    closeButton.setAttribute('id', 'info-close-button');
    closeButton.setAttribute('class', 'button-off');
    closeButton.onclick = () => {
      modal.style.display = 'none';
      shadow.dispatchEvent(this.closeEvent);
    };
    closeButton.innerHTML = '×';

    /* mimic a button hover event */
    closeButton.addEventListener('mouseover', () => {
      closeButton.setAttribute('class', 'button-on');
    });

    closeButton.addEventListener('mouseout', () => {
      closeButton.setAttribute('class', 'button-off');
    });

    // the lightbox
    const modalContent = document.createElement('div');
    modalContent.setAttribute('class', 'modal-content');
    modalContent.setAttribute('id', 'info-modal-content');

    // the main info Content
    const infoContent = document.createElement('div');
    infoContent.setAttribute('id', 'info-content');
    const infoTitle = document.createElement('h3');
    infoTitle.textContent = 'Information';

    // info on pomodoro technique
    const pomoTechHolder = document.createElement('div');
    pomoTechHolder.setAttribute('class', 'info-table');
    const pomoTechLabel = document.createElement('p');
    pomoTechLabel.setAttribute('class', 'info-table-label');
    pomoTechLabel.textContent = 'Pomodoro Technique';
    const pomoTechContent = document.createElement('p');
    pomoTechContent.setAttribute('class', 'info-table-content');
    pomoTechContent.innerHTML = `The Pomodoro Technique was created by 
    <b>Francesco Cirillo</b> in order to better manage time and improve productivity. The 
    traditional <b>Pomodoro Technique</b> consisted of sets. Each set was divided into <b>4</b> 
    work sessions-called pomodoros-with the first 3 followed by a short break and the final 
    work session followed by a long break. Cirillo used <b>25</b> minute pomodoros, <b>5</b> 
    minute short breaks, and <b>15</b> minute long breaks. If a work session is interrupted, that 
    Pomodoro is considered “forfeited” and the user must restart it.`;
    pomoTechHolder.appendChild(pomoTechLabel);
    pomoTechHolder.appendChild(pomoTechContent);

    // info on our web app
    const appHolder = document.createElement('div');
    appHolder.setAttribute('class', 'info-table');
    const appLabel = document.createElement('div');
    appLabel.setAttribute('class', 'info-table-label');
    appLabel.textContent = 'Our Pomodoro App';
    const appContent = document.createElement('p');
    appContent.setAttribute('class', 'info-table-content');
    appContent.innerHTML = `Our app is heavily inspired by the <b>Pomodoro Technique</b>. We use 
    the concept of a set and only allow users to start and reset work sessions and breaks. However, 
    we wanted to allow our users flexibility in modifying the lengths of these intervals to match 
    their work styles.`;
    appHolder.appendChild(appLabel);
    appHolder.appendChild(appContent);

    // info on how to use this web app
    const howToHolder = document.createElement('div');
    howToHolder.setAttribute('class', 'info-table');
    const howToLabel = document.createElement('p');
    howToLabel.setAttribute('class', 'info-table-label');
    howToLabel.textContent = 'How to Use';
    const howToContent = document.createElement('p');
    howToContent.setAttribute('class', 'info-table-content');
    howToContent.innerHTML = `To start using our app, press the <b>Start</b> button or the 
    <kbd>s</kbd> key on your keyboard in order to start the timer. If you need to forfeit 
    and restart the work session for any reason click the <b>Reset</b> button or the 
    <kbd>r</kbd> key on your keyboard. To open up settings, click on <b>'Settings'</b> or 
    use the <kbd>q</kbd> on your keyboard. To open up stats, clikc on<b>'Stats'</b> or 
    use the <kbd>f</kbd> on your keyboard.`;
    howToHolder.appendChild(howToLabel);
    howToHolder.appendChild(howToContent);

    // info on how to change settings
    const settingsHolder = document.createElement('div');
    settingsHolder.setAttribute('class', 'info-table');
    const settingsLabel = document.createElement('p');
    settingsLabel.setAttribute('class', 'info-table-label');
    settingsLabel.textContent = 'How to Use Settings';
    const settingsContent = document.createElement('p');
    settingsContent.setAttribute('class', 'info-table-content');
    settingsContent.innerHTML = `For our settings option, you can customize your timer for:
    <ul>
      <li><b>Work and Break Durations</b></li>
        <ul>
          <li>For Work duration, you can change the duration to be between 
          <b>1 - 60m</b></li>
          <li>For Short Break duration, you can change the duration to be between 
          <b>1 - 60m</b></li>
          <li>For Long Break duration, you can change the duration to be between 
          <b>1 - 60m</b></li>
        </ul>
      <li><b>Calm Mode</b></li>
        <ul>
          <li>If seeing the seconds tick down every second is distracting, you can enable calm 
          mode which will only display the minutes</li>
        </ul>
      <li><b>Dark Mode</b></li>
        <ul>
          <li>Working at night and your screen is too bright? You can enable dark mode</li>
        </ul>
      <li><b>Audio & Volume</b></li>
        <ul>
          <li>If you find yourself tired of hearing the same alarm you can select from various 
          audio selections, as well as changing the volume</li>
        </ul>
      <li><b>Accessibility</b></li>
        <ul>
          <li>If you dislike keyboard shortcuts you can disable them here</li>
        </ul>
    </ul>`;
    settingsHolder.appendChild(settingsLabel);
    settingsHolder.appendChild(settingsContent);

    // info on how to use stats
    const statsHolder = document.createElement('div');
    statsHolder.setAttribute('class', 'info-table');
    const statsLabel = document.createElement('p');
    statsLabel.setAttribute('class', 'info-table-label');
    statsLabel.textContent = 'How to Use Stats';
    const statsContent = document.createElement('p');
    statsContent.setAttribute('class', 'info-table-content');
    statsContent.innerHTML = `For our statistics page, you can see the:
    <ul>
      <li>Amount of Work completed for the day</li>
      <li>Amount of Short Breaks taken</li>
      <li>Amount of Long Breaks taken</li>
      <li>Amount of Work Interruption</li>
    </ul>
    `;
    statsHolder.appendChild(statsLabel);
    statsHolder.appendChild(statsContent);

    // add element to containers
    infoContent.appendChild(infoTitle);
    infoContent.appendChild(pomoTechHolder);
    infoContent.appendChild(appHolder);
    infoContent.appendChild(howToHolder);
    infoContent.appendChild(settingsHolder);
    infoContent.appendChild(statsHolder);

    modalContent.appendChild(closeButton);
    modalContent.appendChild(infoContent);
    modal.appendChild(modalContent);
    wrapper.appendChild(modal);
    wrapper.appendChild(infoButton);

    shadow.appendChild(wrapper);

    // Enabled determines if this component can be opened
    this.enabled = true;

    /**
     * @method
     * Allows the control to open the info page
     */
    this.enableInfo = () => {
      this.enabled = true;
      infoButton.disabled = false;
    };

    /**
     * @method
     * Prevent the control from open the info page
     */
    this.disableInfo = () => {
      this.enabled = false;
      infoButton.disabled = true;
    };

    /**
     * @method
     * Modify elements' data-mode to dark-mode or light-mode
     * @param {Boolean} dark  indicate whether or not the setting is in dark mode
     */
    this.setDark = (dark) => {
      if (dark) {
        infoStyle.setAttribute('href', './components/pomo-info/pomo-info.css');
        infoIcon.setAttribute('src', './assets/images/i_info.png');
      } else {
        infoStyle.setAttribute('href', './components/pomo-info/pomo-info-light.css');
        infoIcon.setAttribute('src', './assets/images/i_info_light.png');
      }
    };

    /**
     * @method
     * For transforming the whole object
     * @param {String} transformText the text to put in transform css
     */
    this.changeTransform = (transformText) => {
      infoButton.style.transform = transformText;
    };

    /**
     * @method
     * For CONTROL to determine whether we can open info, setting, stats
     * @param {Boolean} enabled true for being able to open, false otherwise
     */
    this.setAccessibility = (enabled) => {
      this.accessible = enabled;
    };

    /**
     * Functions that opens and closes the info page with the i key
     */
    document.addEventListener('keydown', (e) => {
      if (e.key === 'i' && this.accessible === true) {
        if (modal.style.display === 'block') {
          closeButton.onclick();
        } else if (this.enabled === true) {
          infoButton.onclick();
        }
      }
    });
  }
}

customElements.define('pomo-info', PomoInfo);

export default PomoInfo;