All files / src BaseSSVG.vue.js

68.75% Statements 33/48
61.53% Branches 16/26
100% Functions 11/11
71.73% Lines 33/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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121                            1x                         3x       3x     1x     3x     3x       8x 4x 4x       5x 5x 5x 3x   2x 1x 1x 1x     5x                       3x 3x           2x 2x       1x 1x       1x 1x                     1x   1x       1x 1x   1x     1x 1x          
// @ts-check
import { first, get } from "lodash";
import Vue from "vue";
import { SSVGEngine } from "@cern/ssvg-engine";
 
import ErrorHandlerMixin from "./mixins/BaseErrorHandlerMixin";
 
/**
 * @typedef {{
 *  svg: HTMLElement
 * }} Refs
 * @typedef {{ engine: SSVGEngine|null }} Options
 */
 
const component = /** @type {V.Constructor<Options, Refs> } */ (Vue).extend({
  name: "BaseSSVG",
  mixins: [ ErrorHandlerMixin ],
  props: {
    iframe: { type: Boolean, default: false },
    src: { type: String, default: null },
    state: { type: Object, default: null },
    preserveAspectRatio: { type: String, default: null }
  },
  /**
   * @return {{ frameLoaded: boolean }}
   */
  data() {
    return { frameLoaded: false };
  },
  computed: {
    /** @return {boolean} */
    hasFrame() { return this.iframe || !!this.src; }
  },
  watch: {
    state() { this.updateState(this.state); }
  },
  mounted() {
    this.reload();
  },
  beforeDestroy() {
    this.release();
  },
  methods: {
    release() {
      if (this.$options.engine) {
        this.$options.engine.disconnect();
        this.$options.engine = null;
      }
    },
    reload() {
      this.release();
      try {
        if (!this.hasFrame) {
          this.$options.engine = new SSVGEngine(this.$refs.svg);
        }
        else if (this.frameLoaded) {
          const svg = this._injectFrame();
          Eif (svg) {
            this.$options.engine = new SSVGEngine(svg);
          }
        }
        Iif (this.state) {
          this.updateState(this.state);
        }
      }
      catch (e) {
        this.onError(e);
      }
    },
    /**
     * @param {any} state
     */
    updateState(state) {
      Iif (!this.$options.engine) { return; }
      this.$options.engine.updateState(state);
    },
    /**
     * @return {any}
     */
    getState() {
      Iif (!this.$options.engine) { return undefined; }
      return this.$options.engine.getState();
    },
    _injectFrame() {
      /** @type {HTMLElement} */
      const document = get(this.$refs.frame, [ "contentDocument" ]);
      Iif (!document) {
        console.warn("iframe unavailable");
        return null;
      }
      var svg = first(document.getElementsByTagName("svg"));
      Iif (!svg) {
        const body = get(document.getElementsByTagName("body"), 0, document);
        const slot = get(this.$slots, [ "default", 0, "elm" ]);
        if (!slot) {
          console.warn("default slot unavailable");
          return null;
        }
        body.appendChild(slot.cloneNode(true));
        body.setAttribute("style", "margin: 0;");
        svg = first(body.getElementsByTagName("svg"));
      }
      Eif (svg) {
        /* we won't be reactive on this, but it's better than nothing */
        Iif (this.preserveAspectRatio) {
          svg.setAttribute("preserveAspectRatio", this.preserveAspectRatio);
        }
        /* Note: set width on parent element */
        svg.setAttribute("width", "100%");
        svg.setAttribute("height", "100%");
      }
      return svg;
    },
    _onFrameLoaded() {
      this.frameLoaded = true;
      this.reload();
    }
  }
});
export default component;