// ========================================================================== // Plyr // plyr.js v3.7.0 // https://github.com/sampotts/plyr // License: The MIT License (MIT) // ========================================================================== import captions from './captions'; import defaults from './config/defaults'; import { pip } from './config/states'; import { getProviderByUrl, providers, types } from './config/types'; import Console from './console'; import controls from './controls'; import Fullscreen from './fullscreen'; import html5 from './html5'; import Listeners from './listeners'; import media from './media'; import Ads from './plugins/ads'; import PreviewThumbnails from './plugins/preview-thumbnails'; import source from './source'; import Storage from './storage'; import support from './support'; import ui from './ui'; import { closest } from './utils/arrays'; import { createElement, hasClass, removeElement, replaceElement, toggleClass, wrap } from './utils/elements'; import { off, on, once, triggerEvent, unbindListeners } from './utils/events'; import is from './utils/is'; import loadSprite from './utils/load-sprite'; import { clamp } from './utils/numbers'; import { cloneDeep, extend } from './utils/objects'; import { silencePromise } from './utils/promise'; import { getAspectRatio, reduceAspectRatio, setAspectRatio, validateAspectRatio } from './utils/style'; import { parseUrl } from './utils/urls'; // Private properties // TODO: Use a WeakMap for private globals // const globals = new WeakMap(); // Plyr instance class Plyr { constructor(target, options) { this.timers = {}; // State this.ready = false; this.loading = false; this.failed = false; // Touch device this.touch = support.touch; // Set the media element this.media = target; // String selector passed if (is.string(this.media)) { this.media = document.querySelectorAll(this.media); } // jQuery, NodeList or Array passed, use first element if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) { // eslint-disable-next-line this.media = this.media[0]; } // Set config this.config = extend( {}, defaults, Plyr.defaults, options || {}, (() => { try { return JSON.parse(this.media.getAttribute('data-plyr-config')); } catch (_) { return {}; } })(), ); // Elements cache this.elements = { container: null, fullscreen: null, captions: null, buttons: {}, display: {}, progress: {}, inputs: {}, settings: { popup: null, menu: null, panels: {}, buttons: {}, }, }; // Captions this.captions = { active: null, currentTrack: -1, meta: new WeakMap(), }; // Fullscreen this.fullscreen = { active: false, }; // Options this.options = { speed: [], quality: [], }; // Debugging // TODO: move to globals this.debug = new Console(this.config.debug); // Log config options and support this.debug.log('Config', this.config); this.debug.log('Support', support); // We need an element to setup if (is.nullOrUndefined(this.media) || !is.element(this.media)) { this.debug.error('Setup failed: no suitable element passed'); return; } // Bail if the element is initialized if (this.media.plyr) { this.debug.warn('Target already setup'); return; } // Bail if not enabled if (!this.config.enabled) { this.debug.error('Setup failed: disabled by config'); return; } // Bail if disabled or no basic support // You may want to disable certain UAs etc if (!support.check().api) { this.debug.error('Setup failed: no support'); return; } // Cache original element state for .destroy() const clone = this.media.cloneNode(true); clone.autoplay = false; this.elements.original = clone; // Set media type based on tag or data attribute // Supported: video, audio, vimeo, youtube const type = this.media.tagName.toLowerCase(); // Embed properties let iframe = null; let url = null; // Different setup based on type switch (type) { case 'div': // Find the frame iframe = this.media.querySelector('iframe'); //