components/SVG/SVGProvider.js

/**
 * SVGProvider is used as container for aplication.
 * Purpose of this container is to load SVG-s from server.
 *
 * @module SVG/SVGProvider
 */
import React from 'react';
import PropTypes from 'prop-types';
import { CNT_PATH, STATIC_VERSION } from '../../constants';

/**
 * @typedef {object} props
 * @property {string} cnt
 * @property {string} wrapperClass
 * @property {object} children
 */
export default class SVGProvider extends React.PureComponent {
  constructor() {
    super();
    /**
     * @member {object}
     * @description Reference on wrapper element
     */
    this.wrapper = undefined;
    /**
     * @member {Array}
     * @description Loaded SVG paths
     */
    this.loadedSVGs = [];
  }

  /**
   * Create context for child components
   *
   * @function
   * @returns {object} SVG object with all functions from container
   */
  getChildContext() {
    return {
      svg: {
        loadedSVGs: this.loadedSVGs,
        checkSvg: this.checkSvg,
        loadSvg: this.loadSvg,
        getIdFromSrc: this.getIdFromSrc,
        getNameFromSrc: this.getNameFromSrc,
      },
    };
  }

  /**
   * Get SVG id
   *
   * @function
   * @param {string} src
   * @returns {string}
   */
  getIdFromSrc = (src) => `#${src.split('#')[1]}`;

  /**
   * Get SVG name
   *
   * @function
   * @param {string} src
   * @returns {string}
   */
  getNameFromSrc = (src) => src.split(/([^/]+(.svg))/)[1];

  /**
   * Get SVG route
   *
   * @function
   * @param {string} src
   * @returns {string}
   */
  getRouteFromSrc = (src) => src.split(/([^]+(.svg))/)[1];

  /**
   * Check if SVG already loaded from server
   *
   * @function
   * @param {string} src
   * @returns {boolean}
   */
  checkSvg = (src) => !!this.loadedSVGs.find((item) => item === this.getNameFromSrc(src));

  /**
   * Load SVG from server
   *
   * @function
   * @param {string} src
   * @returns {void}
   */
  loadSvg = (src) => {
    this.loadedSVGs.push(this.getNameFromSrc(src));
    const route = this.getRouteFromSrc(src);
    // todo put inside a call to get cnt path from server instead of process.env.CNT_PATH
    const ajax = new XMLHttpRequest();
    ajax.open('GET', `${CNT_PATH(this.props.cnt)}/${route}?ver=${STATIC_VERSION}`, true);
    ajax.send();
    ajax.onload = () => {
      if (this.getNameFromSrc(src)) {
        const div = document.createElement('div');
        div.setAttribute('id', this.getNameFromSrc(src));
        div.setAttribute('style', 'height:0px');
        div.innerHTML = ajax.responseText;
        this.wrapper.appendChild(div);
      }
    };
  };

  /**
   * Render
   *
   * @see module:SVG/SVGComponent
   * @returns {view}
   */
  render() {
    return (
      <div className="wrapper" id="wrapper">
        <div
          ref={(ref) => {
            this.wrapper = ref;
          }}
          id="svg-wrapper"
          style={{ height: '0px' }}
        />
        {this.props.children}
      </div>
    );
  }
}

SVGProvider.childContextTypes = {
  svg: PropTypes.object,
};