media-container.js

  1. import { queryOne } from '@ecl/dom-utils';
  2. /**
  3. * @param {HTMLElement} element DOM element for component instantiation and scope
  4. * @param {Object} options
  5. * @param {String} options.iframeSelector Selector for iframe element
  6. * @param {boolean} options.useAutomaticRatio Toggle automatic ratio calculus
  7. */
  8. export class MediaContainer {
  9. /**
  10. * @static
  11. * Shorthand for instance creation and initialisation.
  12. *
  13. * @param {HTMLElement} root DOM element for component instantiation and scope
  14. *
  15. * @return {MediaContainer} An instance of MediaContainer.
  16. */
  17. static autoInit(root, { MEDIA_CONTAINER: defaultOptions = {} } = {}) {
  18. const mediaContainer = new MediaContainer(root, defaultOptions);
  19. mediaContainer.init();
  20. root.ECLMediaContainer = mediaContainer;
  21. return mediaContainer;
  22. }
  23. constructor(
  24. element,
  25. { iframeSelector = 'iframe', useAutomaticRatio = true } = {},
  26. ) {
  27. // Check element
  28. if (!element || element.nodeType !== Node.ELEMENT_NODE) {
  29. throw new TypeError(
  30. 'DOM element should be given to initialize this widget.',
  31. );
  32. }
  33. this.element = element;
  34. // Options
  35. this.iframeSelector = iframeSelector;
  36. this.useAutomaticRatio = useAutomaticRatio;
  37. // Private variables
  38. this.iframe = null;
  39. // Bind `this` for use in callbacks
  40. this.calculateRatio = this.calculateRatio.bind(this);
  41. }
  42. /**
  43. * Initialise component.
  44. */
  45. init() {
  46. if (!ECL) {
  47. throw new TypeError('Called init but ECL is not present');
  48. }
  49. ECL.components = ECL.components || new Map();
  50. // Check if a ratio has been set manually
  51. const media = queryOne('.ecl-media-container__media', this.element);
  52. if (media && !/ecl-media-container__media--ratio/.test(media.className)) {
  53. // Get the iframe
  54. this.iframe = queryOne(this.iframeSelector, this.element);
  55. // Check if there is an iframe to handle
  56. if (this.iframe && this.useAutomaticRatio) this.calculateRatio();
  57. }
  58. // Set ecl initialized attribute
  59. this.element.setAttribute('data-ecl-auto-initialized', 'true');
  60. ECL.components.set(this.element, this);
  61. }
  62. /**
  63. * Destroy component.
  64. */
  65. destroy() {
  66. if (this.element) {
  67. this.element.removeAttribute('data-ecl-auto-initialized');
  68. ECL.components.delete(this.element);
  69. }
  70. }
  71. /**
  72. * Calculate the ratio of the iframe video.
  73. */
  74. calculateRatio() {
  75. // Get dimension if they are provided
  76. let iframeWidth = this.iframe.width;
  77. let iframeHeight = this.iframe.height;
  78. // If at least one dimension in not provided, calculate them (less reliable)
  79. if (!iframeWidth || !iframeHeight) {
  80. iframeWidth = this.iframe.offsetWidth;
  81. iframeHeight = this.iframe.offsetHeight;
  82. }
  83. // Set aspect ratio
  84. this.iframe.style.aspectRatio = `${iframeWidth}/${iframeHeight}`;
  85. }
  86. }
  87. export default MediaContainer;