var St = Object.defineProperty, Et = Object.defineProperties var Pt = Object.getOwnPropertyDescriptors var he = Object.getOwnPropertySymbols var De = Object.prototype.hasOwnProperty, He = Object.prototype.propertyIsEnumerable var Ve = (e, i, t) => i in e ? St(e, i, { enumerable: !0, configurable: !0, writable: !0, value: t }) : (e[i] = t), q = (e, i) => { for (var t in i || (i = {})) De.call(i, t) && Ve(e, t, i[t]) if (he) for (var t of he(i)) He.call(i, t) && Ve(e, t, i[t]) return e }, ie = (e, i) => Et(e, Pt(i)) var Fe = (e, i) => { var t = {} for (var s in e) De.call(e, s) && i.indexOf(s) < 0 && (t[s] = e[s]) if (e != null && he) for (var s of he(e)) i.indexOf(s) < 0 && He.call(e, s) && (t[s] = e[s]) return t } import { d as Nt, a as j, L as Mt, j as Te, F as qe, K as Ue, B as xt, T as It } from './vendor.3506a68e.js' import { l as Lt, b as Ot, p as $t, s as _t } from './index.9e4b607f.js' const Rt = '_video_1vz16_1', jt = '_loadingVideo_1vz16_35', Dt = '_playOver_1vz16_44', Ht = '_tips_1vz16_52', Vt = '_btn_1vz16_56', Ft = '_freeTxt_1vz16_59', qt = '_freeRate_1vz16_65' var U = { 'video-container': '_video-container_1vz16_1', video: Rt, loadingVideo: jt, playOver: Dt, tips: Ht, btn: Vt, freeTxt: Ft, freeRate: qt } function m(e, i, t) { return ( i in e ? Object.defineProperty(e, i, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : (e[i] = t), e ) } function Ut(e, i) { if (!(e instanceof i)) throw new TypeError('Cannot call a class as a function') } function Be(e, i) { for (var t = 0; t < i.length; t++) { var s = i[t] ;(s.enumerable = s.enumerable || !1), (s.configurable = !0), 'value' in s && (s.writable = !0), Object.defineProperty(e, s.key, s) } } function Bt(e, i, t) { return i && Be(e.prototype, i), t && Be(e, t), e } function zt(e, i, t) { return ( i in e ? Object.defineProperty(e, i, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : (e[i] = t), e ) } function ze(e, i) { var t = Object.keys(e) if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e) i && (s = s.filter(function (n) { return Object.getOwnPropertyDescriptor(e, n).enumerable })), t.push.apply(t, s) } return t } function We(e) { for (var i = 1; i < arguments.length; i++) { var t = arguments[i] != null ? arguments[i] : {} i % 2 ? ze(Object(t), !0).forEach(function (s) { zt(e, s, t[s]) }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ze(Object(t)).forEach(function (s) { Object.defineProperty(e, s, Object.getOwnPropertyDescriptor(t, s)) }) } return e } var Ke = { addCSS: !0, thumbWidth: 15, watch: !0 } function Wt(e, i) { return function () { return Array.from(document.querySelectorAll(i)).includes(this) }.call(e, i) } function Kt(e, i) { if (e && i) { var t = new Event(i, { bubbles: !0 }) e.dispatchEvent(t) } } var se = function (e) { return e != null ? e.constructor : null }, ke = function (e, i) { return !!(e && i && e instanceof i) }, Ye = function (e) { return e == null }, Je = function (e) { return se(e) === Object }, Yt = function (e) { return se(e) === Number && !Number.isNaN(e) }, Qe = function (e) { return se(e) === String }, Jt = function (e) { return se(e) === Boolean }, Qt = function (e) { return se(e) === Function }, Xe = function (e) { return Array.isArray(e) }, Ge = function (e) { return ke(e, NodeList) }, Xt = function (e) { return ke(e, Element) }, Gt = function (e) { return ke(e, Event) }, Zt = function (e) { return ( Ye(e) || ((Qe(e) || Xe(e) || Ge(e)) && !e.length) || (Je(e) && !Object.keys(e).length) ) }, R = { nullOrUndefined: Ye, object: Je, number: Yt, string: Qe, boolean: Jt, function: Qt, array: Xe, nodeList: Ge, element: Xt, event: Gt, empty: Zt } function ei(e) { var i = ''.concat(e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/) return i ? Math.max(0, (i[1] ? i[1].length : 0) - (i[2] ? +i[2] : 0)) : 0 } function ti(e, i) { if (1 > i) { var t = ei(i) return parseFloat(e.toFixed(t)) } return Math.round(e / i) * i } var ii = (function () { function e(i, t) { Ut(this, e), R.element(i) ? (this.element = i) : R.string(i) && (this.element = document.querySelector(i)), R.element(this.element) && R.empty(this.element.rangeTouch) && ((this.config = We({}, Ke, {}, t)), this.init()) } return ( Bt( e, [ { key: 'init', value: function () { e.enabled && (this.config.addCSS && ((this.element.style.userSelect = 'none'), (this.element.style.webKitUserSelect = 'none'), (this.element.style.touchAction = 'manipulation')), this.listeners(!0), (this.element.rangeTouch = this)) } }, { key: 'destroy', value: function () { e.enabled && (this.config.addCSS && ((this.element.style.userSelect = ''), (this.element.style.webKitUserSelect = ''), (this.element.style.touchAction = '')), this.listeners(!1), (this.element.rangeTouch = null)) } }, { key: 'listeners', value: function (i) { var t = this, s = i ? 'addEventListener' : 'removeEventListener' ;['touchstart', 'touchmove', 'touchend'].forEach(function (n) { t.element[s]( n, function (a) { return t.set(a) }, !1 ) }) } }, { key: 'get', value: function (i) { if (!e.enabled || !R.event(i)) return null var t, s = i.target, n = i.changedTouches[0], a = parseFloat(s.getAttribute('min')) || 0, r = parseFloat(s.getAttribute('max')) || 100, o = parseFloat(s.getAttribute('step')) || 1, c = s.getBoundingClientRect(), u = ((100 / c.width) * (this.config.thumbWidth / 2)) / 100 return ( 0 > (t = (100 / c.width) * (n.clientX - c.left)) ? (t = 0) : 100 < t && (t = 100), 50 > t ? (t -= (100 - 2 * t) * u) : 50 < t && (t += 2 * (t - 50) * u), a + ti((t / 100) * (r - a), o) ) } }, { key: 'set', value: function (i) { e.enabled && R.event(i) && !i.target.disabled && (i.preventDefault(), (i.target.value = this.get(i)), Kt(i.target, i.type === 'touchend' ? 'change' : 'input')) } } ], [ { key: 'setup', value: function (i) { var t = 1 < arguments.length && arguments[1] !== void 0 ? arguments[1] : {}, s = null if ( (R.empty(i) || R.string(i) ? (s = Array.from( document.querySelectorAll( R.string(i) ? i : 'input[type="range"]' ) )) : R.element(i) ? (s = [i]) : R.nodeList(i) ? (s = Array.from(i)) : R.array(i) && (s = i.filter(R.element)), R.empty(s)) ) return null var n = We({}, Ke, {}, t) if (R.string(i) && n.watch) { var a = new MutationObserver(function (r) { Array.from(r).forEach(function (o) { Array.from(o.addedNodes).forEach(function (c) { R.element(c) && Wt(c, i) && new e(c, n) }) }) }) a.observe(document.body, { childList: !0, subtree: !0 }) } return s.map(function (r) { return new e(r, t) }) } }, { key: 'enabled', get: function () { return 'ontouchstart' in document.documentElement } } ] ), e ) })() const G = e => (e != null ? e.constructor : null), B = (e, i) => Boolean(e && i && e instanceof i), Ae = e => e == null, Ze = e => G(e) === Object, si = e => G(e) === Number && !Number.isNaN(e), de = e => G(e) === String, ni = e => G(e) === Boolean, et = e => G(e) === Function, tt = e => Array.isArray(e), ai = e => B(e, WeakMap), it = e => B(e, NodeList), li = e => G(e) === Text, ri = e => B(e, Event), oi = e => B(e, KeyboardEvent), ci = e => B(e, window.TextTrackCue) || B(e, window.VTTCue), ui = e => B(e, TextTrack) || (!Ae(e) && de(e.kind)), hi = e => B(e, Promise) && et(e.then), di = e => e !== null && typeof e == 'object' && e.nodeType === 1 && typeof e.style == 'object' && typeof e.ownerDocument == 'object', st = e => Ae(e) || ((de(e) || tt(e) || it(e)) && !e.length) || (Ze(e) && !Object.keys(e).length), mi = e => { if (B(e, window.URL)) return !0 if (!de(e)) return !1 let i = e ;(e.startsWith('http://') && e.startsWith('https://')) || (i = `http://${e}`) try { return !st(new URL(i).hostname) } catch { return !1 } } var l = { nullOrUndefined: Ae, object: Ze, number: si, string: de, boolean: ni, function: et, array: tt, weakMap: ai, nodeList: it, element: di, textNode: li, event: ri, keyboardEvent: oi, cue: ci, track: ui, promise: hi, url: mi, empty: st } const Ce = (() => { const e = document.createElement('span'), i = { WebkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'oTransitionEnd otransitionend', transition: 'transitionend' }, t = Object.keys(i).find(s => e.style[s] !== void 0) return !!l.string(t) && i[t] })() function nt(e, i) { setTimeout(() => { try { ;(e.hidden = !0), e.offsetHeight, (e.hidden = !1) } catch {} }, i) } const _ = { isIE: Boolean(window.document.documentMode), isEdge: window.navigator.userAgent.includes('Edge'), isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), isIos: (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) || /(iPad|iPhone|iPod)/gi.test(navigator.platform) } function pi(e) { return JSON.parse(JSON.stringify(e)) } function at(e, i) { return i.split('.').reduce((t, s) => t && t[s], e) } function I(e = {}, ...i) { if (!i.length) return e const t = i.shift() return l.object(t) ? (Object.keys(t).forEach(s => { l.object(t[s]) ? (Object.keys(e).includes(s) || Object.assign(e, { [s]: {} }), I(e[s], t[s])) : Object.assign(e, { [s]: t[s] }) }), I(e, ...i)) : e } function lt(e, i) { const t = e.length ? e : [e] Array.from(t) .reverse() .forEach((s, n) => { const a = n > 0 ? i.cloneNode(!0) : i, r = s.parentNode, o = s.nextSibling a.appendChild(s), o ? r.insertBefore(a, o) : r.appendChild(a) }) } function Se(e, i) { l.element(e) && !l.empty(i) && Object.entries(i) .filter(([, t]) => !l.nullOrUndefined(t)) .forEach(([t, s]) => e.setAttribute(t, s)) } function y(e, i, t) { const s = document.createElement(e) return l.object(i) && Se(s, i), l.string(t) && (s.innerText = t), s } function gi(e, i) { l.element(e) && l.element(i) && i.parentNode.insertBefore(e, i.nextSibling) } function rt(e, i, t, s) { l.element(i) && i.appendChild(y(e, t, s)) } function z(e) { l.nodeList(e) || l.array(e) ? Array.from(e).forEach(z) : l.element(e) && l.element(e.parentNode) && e.parentNode.removeChild(e) } function me(e) { if (!l.element(e)) return let { length: i } = e.childNodes for (; i > 0; ) e.removeChild(e.lastChild), (i -= 1) } function pe(e, i) { return l.element(i) && l.element(i.parentNode) && l.element(e) ? (i.parentNode.replaceChild(e, i), e) : null } function H(e, i) { if (!l.string(e) || l.empty(e)) return {} const t = {}, s = I({}, i) return ( e.split(',').forEach(n => { const a = n.trim(), r = a.replace('.', ''), o = a.replace(/[[\]]/g, '').split('='), [c] = o, u = o.length > 1 ? o[1].replace(/["']/g, '') : '' switch (a.charAt(0)) { case '.': l.string(s.class) ? (t.class = `${s.class} ${r}`) : (t.class = r) break case '#': t.id = a.replace('#', '') break case '[': t[c] = u } }), I(s, t) ) } function J(e, i) { if (!l.element(e)) return let t = i l.boolean(t) || (t = !e.hidden), (e.hidden = t) } function A(e, i, t) { if (l.nodeList(e)) return Array.from(e).map(s => A(s, i, t)) if (l.element(e)) { let s = 'toggle' return ( t !== void 0 && (s = t ? 'add' : 'remove'), e.classList[s](i), e.classList.contains(i) ) } return !1 } function ge(e, i) { return l.element(e) && e.classList.contains(i) } function Q(e, i) { const { prototype: t } = Element return ( t.matches || t.webkitMatchesSelector || t.mozMatchesSelector || t.msMatchesSelector || function () { return Array.from(document.querySelectorAll(i)).includes(this) } ).call(e, i) } function fi(e, i) { const { prototype: t } = Element return ( t.closest || function () { let s = this do { if (Q.matches(s, i)) return s s = s.parentElement || s.parentNode } while (s !== null && s.nodeType === 1) return null } ).call(e, i) } function Z(e) { return this.elements.container.querySelectorAll(e) } function O(e) { return this.elements.container.querySelector(e) } function Ee(e = null, i = !1) { l.element(e) && (e.focus({ preventScroll: !0 }), i && A(e, this.config.classNames.tabFocus)) } const ot = { 'audio/ogg': 'vorbis', 'audio/wav': '1', 'video/webm': 'vp8, vorbis', 'video/mp4': 'avc1.42E01E, mp4a.40.2', 'video/ogg': 'theora' }, x = { audio: 'canPlayType' in document.createElement('audio'), video: 'canPlayType' in document.createElement('video'), check(e, i, t) { const s = _.isIPhone && t && x.playsinline, n = x[e] || i !== 'html5' return { api: n, ui: n && x.rangeInput && (e !== 'video' || !_.isIPhone || s) } }, pip: !( _.isIPhone || (!l.function(y('video').webkitSetPresentationMode) && (!document.pictureInPictureEnabled || y('video').disablePictureInPicture)) ), airplay: l.function(window.WebKitPlaybackTargetAvailabilityEvent), playsinline: 'playsInline' in document.createElement('video'), mime(e) { if (l.empty(e)) return !1 const [i] = e.split('/') let t = e if (!this.isHTML5 || i !== this.type) return !1 Object.keys(ot).includes(t) && (t += `; codecs="${ot[e]}"`) try { return Boolean(t && this.media.canPlayType(t).replace(/no/, '')) } catch { return !1 } }, textTracks: 'textTracks' in document.createElement('video'), rangeInput: (() => { const e = document.createElement('input') return (e.type = 'range'), e.type === 'range' })(), touch: 'ontouchstart' in document.documentElement, transitions: Ce !== !1, reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches }, yi = (() => { let e = !1 try { const i = Object.defineProperty({}, 'passive', { get: () => ((e = !0), null) }) window.addEventListener('test', null, i), window.removeEventListener('test', null, i) } catch {} return e })() function ee(e, i, t, s = !1, n = !0, a = !1) { if (!e || !('addEventListener' in e) || l.empty(i) || !l.function(t)) return const r = i.split(' ') let o = a yi && (o = { passive: n, capture: a }), r.forEach(c => { this && this.eventListeners && s && this.eventListeners.push({ element: e, type: c, callback: t, options: o }), e[s ? 'addEventListener' : 'removeEventListener'](c, t, o) }) } function C(e, i = '', t, s = !0, n = !1) { ee.call(this, e, i, t, !0, s, n) } function fe(e, i = '', t, s = !0, n = !1) { ee.call(this, e, i, t, !1, s, n) } function Pe(e, i = '', t, s = !0, n = !1) { const a = (...r) => { fe(e, i, a, s, n), t.apply(this, r) } ee.call(this, e, i, a, !0, s, n) } function b(e, i = '', t = !1, s = {}) { if (!l.element(e) || l.empty(i)) return const n = new CustomEvent(i, { bubbles: t, detail: ie(q({}, s), { plyr: this }) }) e.dispatchEvent(n) } function bi() { this && this.eventListeners && (this.eventListeners.forEach(e => { const { element: i, type: t, callback: s, options: n } = e i.removeEventListener(t, s, n) }), (this.eventListeners = [])) } function vi() { return new Promise(e => this.ready ? setTimeout(e, 0) : C.call(this, this.elements.container, 'ready', e) ).then(() => {}) } function V(e) { l.promise(e) && e.then(null, () => {}) } function Ne(e) { return l.array(e) ? e.filter((i, t) => e.indexOf(i) === t) : e } function ct(e, i) { return l.array(e) && e.length ? e.reduce((t, s) => (Math.abs(s - i) < Math.abs(t - i) ? s : t)) : null } function ut(e) { return !(!window || !window.CSS) && window.CSS.supports(e) } const ht = [ [1, 1], [4, 3], [3, 4], [5, 4], [4, 5], [3, 2], [2, 3], [16, 10], [10, 16], [16, 9], [9, 16], [21, 9], [9, 21], [32, 9], [9, 32] ].reduce((e, [i, t]) => ie(q({}, e), { [i / t]: [i, t] }), {}) function dt(e) { return l.array(e) || (l.string(e) && e.includes(':')) ? (l.array(e) ? e : e.split(':')).map(Number).every(l.number) : !1 } function ye(e) { if (!l.array(e) || !e.every(l.number)) return null const [i, t] = e, s = (a, r) => (r === 0 ? a : s(r, a % r)), n = s(i, t) return [i / n, t / n] } function Me(e) { const i = s => (dt(s) ? s.split(':').map(Number) : null) let t = i(e) if ( (t === null && (t = i(this.config.ratio)), t === null && !l.empty(this.embed) && l.array(this.embed.ratio) && ({ ratio: t } = this.embed), t === null && this.isHTML5) ) { const { videoWidth: s, videoHeight: n } = this.media t = [s, n] } return ye(t) } function te(e) { if (!this.isVideo) return {} const { wrapper: i } = this.elements, t = Me.call(this, e) if (!l.array(t)) return {} const [s, n] = ye(t), a = (100 / s) * n if ( (ut(`aspect-ratio: ${s}/${n}`) ? (i.style.aspectRatio = `${s}/${n}`) : (i.style.paddingBottom = `${a}%`), this.isVimeo && !this.config.vimeo.premium && this.supported.ui) ) { const r = (100 / this.media.offsetWidth) * parseInt(window.getComputedStyle(this.media).paddingBottom, 10), o = (r - a) / (r / 50) this.fullscreen.active ? (i.style.paddingBottom = null) : (this.media.style.transform = `translateY(-${o}%)`) } else this.isHTML5 && i.classList.add(this.config.classNames.videoFixedRatio) return { padding: a, ratio: t } } function mt(e, i, t = 0.05) { const s = e / i, n = ct(Object.keys(ht), s) return Math.abs(n - s) <= t ? ht[n] : [e, i] } function wi() { return [ Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0), Math.max( document.documentElement.clientHeight || 0, window.innerHeight || 0 ) ] } const K = { getSources() { return this.isHTML5 ? Array.from(this.media.querySelectorAll('source')).filter(e => { const i = e.getAttribute('type') return !!l.empty(i) || x.mime.call(this, i) }) : [] }, getQualityOptions() { return this.config.quality.forced ? this.config.quality.options : K.getSources .call(this) .map(e => Number(e.getAttribute('size'))) .filter(Boolean) }, setup() { if (!this.isHTML5) return const e = this ;(e.options.speed = e.config.speed.options), l.empty(this.config.ratio) || te.call(e), Object.defineProperty(e.media, 'quality', { get() { const i = K.getSources .call(e) .find(t => t.getAttribute('src') === e.source) return i && Number(i.getAttribute('size')) }, set(i) { if (e.quality !== i) { if ( e.config.quality.forced && l.function(e.config.quality.onChange) ) e.config.quality.onChange(i) else { const t = K.getSources .call(e) .find(c => Number(c.getAttribute('size')) === i) if (!t) return const { currentTime: s, paused: n, preload: a, readyState: r, playbackRate: o } = e.media ;(e.media.src = t.getAttribute('src')), (a !== 'none' || r) && (e.once('loadedmetadata', () => { ;(e.speed = o), (e.currentTime = s), n || V(e.play()) }), e.media.load()) } b.call(e, e.media, 'qualitychange', !1, { quality: i }) } } }) }, cancelRequests() { this.isHTML5 && (z(K.getSources.call(this)), this.media.setAttribute('src', this.config.blankVideo), this.media.load(), this.debug.log('Cancelled network requests')) } } function Ti(e) { return `${e}-${Math.floor(1e4 * Math.random())}` } function xe(e, ...i) { return l.empty(e) ? e : e.toString().replace(/{(\d+)}/g, (t, s) => i[s].toString()) } function ki(e, i) { return e === 0 || i === 0 || Number.isNaN(e) || Number.isNaN(i) ? 0 : ((e / i) * 100).toFixed(2) } const ne = (e = '', i = '', t = '') => e.replace( new RegExp( i.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g' ), t.toString() ), pt = (e = '') => e .toString() .replace( /\w\S*/g, i => i.charAt(0).toUpperCase() + i.slice(1).toLowerCase() ) function Ai(e = '') { let i = e.toString() return ( (i = ne(i, '-', ' ')), (i = ne(i, '_', ' ')), (i = pt(i)), ne(i, ' ', '') ) } function Ci(e = '') { let i = e.toString() return (i = Ai(i)), i.charAt(0).toLowerCase() + i.slice(1) } function Si(e) { const i = document.createDocumentFragment(), t = document.createElement('div') return i.appendChild(t), (t.innerHTML = e), i.firstChild.innerText } function Ei(e) { const i = document.createElement('div') return i.appendChild(e), i.innerHTML } const gt = { pip: 'PIP', airplay: 'AirPlay', html5: 'HTML5', vimeo: 'Vimeo', youtube: 'YouTube' }, $ = { get(e = '', i = {}) { if (l.empty(e) || l.empty(i)) return '' let t = at(i.i18n, e) if (l.empty(t)) return Object.keys(gt).includes(e) ? gt[e] : '' const s = { '{seektime}': i.seekTime, '{title}': i.title } return ( Object.entries(s).forEach(([n, a]) => { t = ne(t, n, a) }), t ) } } class ae { constructor(i) { m(this, 'get', t => { if (!ae.supported || !this.enabled) return null const s = window.localStorage.getItem(this.key) if (l.empty(s)) return null const n = JSON.parse(s) return l.string(t) && t.length ? n[t] : n }), m(this, 'set', t => { if (!ae.supported || !this.enabled || !l.object(t)) return let s = this.get() l.empty(s) && (s = {}), I(s, t) try { window.localStorage.setItem(this.key, JSON.stringify(s)) } catch {} }), (this.enabled = i.config.storage.enabled), (this.key = i.config.storage.key) } static get supported() { try { if (!('localStorage' in window)) return !1 const i = '___test' return ( window.localStorage.setItem(i, i), window.localStorage.removeItem(i), !0 ) } catch { return !1 } } } function le(e, i = 'text') { return new Promise((t, s) => { try { const n = new XMLHttpRequest() if (!('withCredentials' in n)) return n.addEventListener('load', () => { if (i === 'text') try { t(JSON.parse(n.responseText)) } catch { t(n.responseText) } else t(n.response) }), n.addEventListener('error', () => { throw new Error(n.status) }), n.open('GET', e, !0), (n.responseType = i), n.send() } catch (n) { s(n) } }) } function ft(e, i) { if (!l.string(e)) return const t = l.string(i) let s = !1 const n = () => document.getElementById(i) !== null, a = (r, o) => { ;(r.innerHTML = o), (t && n()) || document.body.insertAdjacentElement('afterbegin', r) } if (!t || !n()) { const r = ae.supported, o = document.createElement('div') if ((o.setAttribute('hidden', ''), t && o.setAttribute('id', i), r)) { const c = window.localStorage.getItem(`cache-${i}`) if (((s = c !== null), s)) { const u = JSON.parse(c) a(o, u.content) } } le(e) .then(c => { if (!l.empty(c)) { if (r) try { window.localStorage.setItem( `cache-${i}`, JSON.stringify({ content: c }) ) } catch {} a(o, c) } }) .catch(() => {}) } } const yt = e => Math.trunc((e / 60 / 60) % 60, 10), Pi = e => Math.trunc(e % 60, 10) function be(e = 0, i = !1, t = !1) { if (!l.number(e)) return be(void 0, i, t) const s = c => `0${c}`.slice(-2) let n = yt(e) const a = ((r = e), Math.trunc((r / 60) % 60, 10)) var r const o = Pi(e) return ( (n = i || n > 0 ? `${n}:` : ''), `${t && e > 0 ? '-' : ''}${n}${s(a)}:${s(o)}` ) } const h = { getIconUrl() { const e = new URL(this.config.iconUrl, window.location), i = window.location.host ? window.location.host : window.top.location.host, t = e.host !== i || (_.isIE && !window.svg4everybody) return { url: this.config.iconUrl, cors: t } }, findElements() { try { return ( (this.elements.controls = O.call( this, this.config.selectors.controls.wrapper )), (this.elements.buttons = { play: Z.call(this, this.config.selectors.buttons.play), pause: O.call(this, this.config.selectors.buttons.pause), restart: O.call(this, this.config.selectors.buttons.restart), rewind: O.call(this, this.config.selectors.buttons.rewind), fastForward: O.call(this, this.config.selectors.buttons.fastForward), mute: O.call(this, this.config.selectors.buttons.mute), pip: O.call(this, this.config.selectors.buttons.pip), airplay: O.call(this, this.config.selectors.buttons.airplay), settings: O.call(this, this.config.selectors.buttons.settings), captions: O.call(this, this.config.selectors.buttons.captions), fullscreen: O.call(this, this.config.selectors.buttons.fullscreen) }), (this.elements.progress = O.call(this, this.config.selectors.progress)), (this.elements.inputs = { seek: O.call(this, this.config.selectors.inputs.seek), volume: O.call(this, this.config.selectors.inputs.volume) }), (this.elements.display = { buffer: O.call(this, this.config.selectors.display.buffer), currentTime: O.call(this, this.config.selectors.display.currentTime), duration: O.call(this, this.config.selectors.display.duration) }), l.element(this.elements.progress) && (this.elements.display.seekTooltip = this.elements.progress.querySelector( `.${this.config.classNames.tooltip}` )), !0 ) } catch (e) { return ( this.debug.warn( 'It looks like there is a problem with your custom controls HTML', e ), this.toggleNativeControls(!0), !1 ) } }, createIcon(e, i) { const t = 'http://www.w3.org/2000/svg', s = h.getIconUrl.call(this), n = `${s.cors ? '' : s.url}#${this.config.iconPrefix}`, a = document.createElementNS(t, 'svg') Se(a, I(i, { 'aria-hidden': 'true', focusable: 'false' })) const r = document.createElementNS(t, 'use'), o = `${n}-${e}` return ( 'href' in r && r.setAttributeNS('http://www.w3.org/1999/xlink', 'href', o), r.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', o), a.appendChild(r), a ) }, createLabel(e, i = {}) { const t = $.get(e, this.config) return y( 'span', ie(q({}, i), { class: [i.class, this.config.classNames.hidden] .filter(Boolean) .join(' ') }), t ) }, createBadge(e) { if (l.empty(e)) return null const i = y('span', { class: this.config.classNames.menu.value }) return ( i.appendChild(y('span', { class: this.config.classNames.menu.badge }, e)), i ) }, createButton(e, i) { const t = I({}, i) let s = Ci(e) const n = { element: 'button', toggle: !1, label: null, icon: null, labelPressed: null, iconPressed: null } switch ( (['element', 'icon', 'label'].forEach(r => { Object.keys(t).includes(r) && ((n[r] = t[r]), delete t[r]) }), n.element !== 'button' || Object.keys(t).includes('type') || (t.type = 'button'), Object.keys(t).includes('class') ? t.class.split(' ').some(r => r === this.config.classNames.control) || I(t, { class: `${t.class} ${this.config.classNames.control}` }) : (t.class = this.config.classNames.control), e) ) { case 'play': ;(n.toggle = !0), (n.label = 'play'), (n.labelPressed = 'pause'), (n.icon = 'play'), (n.iconPressed = 'pause') break case 'mute': ;(n.toggle = !0), (n.label = 'mute'), (n.labelPressed = 'unmute'), (n.icon = 'volume'), (n.iconPressed = 'muted') break case 'captions': ;(n.toggle = !0), (n.label = 'enableCaptions'), (n.labelPressed = 'disableCaptions'), (n.icon = 'captions-off'), (n.iconPressed = 'captions-on') break case 'fullscreen': ;(n.toggle = !0), (n.label = 'enterFullscreen'), (n.labelPressed = 'exitFullscreen'), (n.icon = 'enter-fullscreen'), (n.iconPressed = 'exit-fullscreen') break case 'play-large': ;(t.class += ` ${this.config.classNames.control}--overlaid`), (s = 'play'), (n.label = 'play'), (n.icon = 'play') break default: l.empty(n.label) && (n.label = s), l.empty(n.icon) && (n.icon = e) } const a = y(n.element) return ( n.toggle ? (a.appendChild( h.createIcon.call(this, n.iconPressed, { class: 'icon--pressed' }) ), a.appendChild( h.createIcon.call(this, n.icon, { class: 'icon--not-pressed' }) ), a.appendChild( h.createLabel.call(this, n.labelPressed, { class: 'label--pressed' }) ), a.appendChild( h.createLabel.call(this, n.label, { class: 'label--not-pressed' }) )) : (a.appendChild(h.createIcon.call(this, n.icon)), a.appendChild(h.createLabel.call(this, n.label))), I(t, H(this.config.selectors.buttons[s], t)), Se(a, t), s === 'play' ? (l.array(this.elements.buttons[s]) || (this.elements.buttons[s] = []), this.elements.buttons[s].push(a)) : (this.elements.buttons[s] = a), a ) }, createRange(e, i) { const t = y( 'input', I( H(this.config.selectors.inputs[e]), { type: 'range', min: 0, max: 100, step: 0.01, value: 0, autocomplete: 'off', role: 'slider', 'aria-label': $.get(e, this.config), 'aria-valuemin': 0, 'aria-valuemax': 100, 'aria-valuenow': 0 }, i ) ) return ( (this.elements.inputs[e] = t), h.updateRangeFill.call(this, t), ii.setup(t), t ) }, createProgress(e, i) { const t = y( 'progress', I( H(this.config.selectors.display[e]), { min: 0, max: 100, value: 0, role: 'progressbar', 'aria-hidden': !0 }, i ) ) if (e !== 'volume') { t.appendChild(y('span', null, '0')) const s = { played: 'played', buffer: 'buffered' }[e], n = s ? $.get(s, this.config) : '' t.innerText = `% ${n.toLowerCase()}` } return (this.elements.display[e] = t), t }, createTime(e, i) { const t = H(this.config.selectors.display[e], i), s = y( 'div', I(t, { class: `${t.class ? t.class : ''} ${ this.config.classNames.display.time } `.trim(), 'aria-label': $.get(e, this.config) }), '00:00' ) return (this.elements.display[e] = s), s }, bindMenuItemShortcuts(e, i) { C.call( this, e, 'keydown keyup', t => { if ( !['Space', 'ArrowUp', 'ArrowDown', 'ArrowRight'].includes(t.key) || (t.preventDefault(), t.stopPropagation(), t.type === 'keydown') ) return const s = Q(e, '[role="menuitemradio"]') if (!s && ['Space', 'ArrowRight'].includes(t.key)) h.showMenuPanel.call(this, i, !0) else { let n t.key !== 'Space' && (t.key === 'ArrowDown' || (s && t.key === 'ArrowRight') ? ((n = e.nextElementSibling), l.element(n) || (n = e.parentNode.firstElementChild)) : ((n = e.previousElementSibling), l.element(n) || (n = e.parentNode.lastElementChild)), Ee.call(this, n, !0)) } }, !1 ), C.call(this, e, 'keyup', t => { t.key === 'Return' && h.focusFirstMenuItem.call(this, null, !0) }) }, createMenuItem({ value: e, list: i, type: t, title: s, badge: n = null, checked: a = !1 }) { const r = H(this.config.selectors.inputs[t]), o = y( 'button', I(r, { type: 'button', role: 'menuitemradio', class: `${this.config.classNames.control} ${ r.class ? r.class : '' }`.trim(), 'aria-checked': a, value: e }) ), c = y('span') ;(c.innerHTML = s), l.element(n) && c.appendChild(n), o.appendChild(c), Object.defineProperty(o, 'checked', { enumerable: !0, get: () => o.getAttribute('aria-checked') === 'true', set(u) { u && Array.from(o.parentNode.children) .filter(p => Q(p, '[role="menuitemradio"]')) .forEach(p => p.setAttribute('aria-checked', 'false')), o.setAttribute('aria-checked', u ? 'true' : 'false') } }), this.listeners.bind( o, 'click keyup', u => { if (!l.keyboardEvent(u) || u.key === 'Space') { switch ( (u.preventDefault(), u.stopPropagation(), (o.checked = !0), t) ) { case 'language': this.currentTrack = Number(e) break case 'quality': this.quality = e break case 'speed': this.speed = parseFloat(e) } h.showMenuPanel.call(this, 'home', l.keyboardEvent(u)) } }, t, !1 ), h.bindMenuItemShortcuts.call(this, o, t), i.appendChild(o) }, formatTime(e = 0, i = !1) { return l.number(e) ? be(e, yt(this.duration) > 0, i) : e }, updateTimeDisplay(e = null, i = 0, t = !1) { l.element(e) && l.number(i) && (e.innerText = h.formatTime(i, t)) }, updateVolume() { this.supported.ui && (l.element(this.elements.inputs.volume) && h.setRange.call( this, this.elements.inputs.volume, this.muted ? 0 : this.volume ), l.element(this.elements.buttons.mute) && (this.elements.buttons.mute.pressed = this.muted || this.volume === 0)) }, setRange(e, i = 0) { l.element(e) && ((e.value = i), h.updateRangeFill.call(this, e)) }, updateProgress(e) { if (!this.supported.ui || !l.event(e)) return let i = 0 const t = (s, n) => { const a = l.number(n) ? n : 0, r = l.element(s) ? s : this.elements.display.buffer if (l.element(r)) { r.value = a const o = r.getElementsByTagName('span')[0] l.element(o) && (o.childNodes[0].nodeValue = a) } } if (e) switch (e.type) { case 'timeupdate': case 'seeking': case 'seeked': ;(i = ki(this.currentTime, this.duration)), e.type === 'timeupdate' && h.setRange.call(this, this.elements.inputs.seek, i) break case 'playing': case 'progress': t(this.elements.display.buffer, 100 * this.buffered) } }, updateRangeFill(e) { const i = l.event(e) ? e.target : e if (l.element(i) && i.getAttribute('type') === 'range') { if (Q(i, this.config.selectors.inputs.seek)) { i.setAttribute('aria-valuenow', this.currentTime) const t = h.formatTime(this.currentTime), s = h.formatTime(this.duration), n = $.get('seekLabel', this.config) i.setAttribute( 'aria-valuetext', n.replace('{currentTime}', t).replace('{duration}', s) ) } else if (Q(i, this.config.selectors.inputs.volume)) { const t = 100 * i.value i.setAttribute('aria-valuenow', t), i.setAttribute('aria-valuetext', `${t.toFixed(1)}%`) } else i.setAttribute('aria-valuenow', i.value) _.isWebkit && i.style.setProperty('--value', (i.value / i.max) * 100 + '%') } }, updateSeekTooltip(e) { var i, t if ( !this.config.tooltips.seek || !l.element(this.elements.inputs.seek) || !l.element(this.elements.display.seekTooltip) || this.duration === 0 ) return const s = this.elements.display.seekTooltip, n = `${this.config.classNames.tooltip}--visible`, a = p => A(s, n, p) if (this.touch) return void a(!1) let r = 0 const o = this.elements.progress.getBoundingClientRect() if (l.event(e)) r = (100 / o.width) * (e.pageX - o.left) else { if (!ge(s, n)) return r = parseFloat(s.style.left, 10) } r < 0 ? (r = 0) : r > 100 && (r = 100) const c = (this.duration / 100) * r s.innerText = h.formatTime(c) const u = (i = this.config.markers) === null || i === void 0 || (t = i.points) === null || t === void 0 ? void 0 : t.find(({ time: p }) => p === Math.round(c)) u && s.insertAdjacentHTML('afterbegin', `${u.label}
`), (s.style.left = `${r}%`), l.event(e) && ['mouseenter', 'mouseleave'].includes(e.type) && a(e.type === 'mouseenter') }, timeUpdate(e) { const i = !l.element(this.elements.display.duration) && this.config.invertTime h.updateTimeDisplay.call( this, this.elements.display.currentTime, i ? this.duration - this.currentTime : this.currentTime, i ), (e && e.type === 'timeupdate' && this.media.seeking) || h.updateProgress.call(this, e) }, durationUpdate() { if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) return if (this.duration >= 2 ** 32) return ( J(this.elements.display.currentTime, !0), void J(this.elements.progress, !0) ) l.element(this.elements.inputs.seek) && this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration) const e = l.element(this.elements.display.duration) !e && this.config.displayDuration && this.paused && h.updateTimeDisplay.call( this, this.elements.display.currentTime, this.duration ), e && h.updateTimeDisplay.call( this, this.elements.display.duration, this.duration ), this.config.markers.enabled && h.setMarkers.call(this), h.updateSeekTooltip.call(this) }, toggleMenuButton(e, i) { J(this.elements.settings.buttons[e], !i) }, updateSetting(e, i, t) { const s = this.elements.settings.panels[e] let n = null, a = i if (e === 'captions') n = this.currentTrack else { if ( ((n = l.empty(t) ? this[e] : t), l.empty(n) && (n = this.config[e].default), !l.empty(this.options[e]) && !this.options[e].includes(n)) ) return void this.debug.warn(`Unsupported value of '${n}' for ${e}`) if (!this.config[e].options.includes(n)) return void this.debug.warn(`Disabled value of '${n}' for ${e}`) } if ( (l.element(a) || (a = s && s.querySelector('[role="menu"]')), !l.element(a)) ) return this.elements.settings.buttons[e].querySelector( `.${this.config.classNames.menu.value}` ).innerHTML = h.getLabel.call(this, e, n) const r = a && a.querySelector(`[value="${n}"]`) l.element(r) && (r.checked = !0) }, getLabel(e, i) { switch (e) { case 'speed': return i === 1 ? $.get('normal', this.config) : `${i}×` case 'quality': if (l.number(i)) { const t = $.get(`qualityLabel.${i}`, this.config) return t.length ? t : `${i}p` } return pt(i) case 'captions': return E.getLabel.call(this) default: return null } }, setQualityMenu(e) { if (!l.element(this.elements.settings.panels.quality)) return const i = 'quality', t = this.elements.settings.panels.quality.querySelector('[role="menu"]') l.array(e) && (this.options.quality = Ne(e).filter(a => this.config.quality.options.includes(a) )) const s = !l.empty(this.options.quality) && this.options.quality.length > 1 if ( (h.toggleMenuButton.call(this, i, s), me(t), h.checkMenu.call(this), !s) ) return const n = a => { const r = $.get(`qualityBadge.${a}`, this.config) return r.length ? h.createBadge.call(this, r) : null } this.options.quality .sort((a, r) => { const o = this.config.quality.options return o.indexOf(a) > o.indexOf(r) ? 1 : -1 }) .forEach(a => { h.createMenuItem.call(this, { value: a, list: t, type: i, title: h.getLabel.call(this, 'quality', a), badge: n(a) }) }), h.updateSetting.call(this, i, t) }, setCaptionsMenu() { if (!l.element(this.elements.settings.panels.captions)) return const e = 'captions', i = this.elements.settings.panels.captions.querySelector('[role="menu"]'), t = E.getTracks.call(this), s = Boolean(t.length) if ( (h.toggleMenuButton.call(this, e, s), me(i), h.checkMenu.call(this), !s) ) return const n = t.map((a, r) => ({ value: r, checked: this.captions.toggled && this.currentTrack === r, title: E.getLabel.call(this, a), badge: a.language && h.createBadge.call(this, a.language.toUpperCase()), list: i, type: 'language' })) n.unshift({ value: -1, checked: !this.captions.toggled, title: $.get('disabled', this.config), list: i, type: 'language' }), n.forEach(h.createMenuItem.bind(this)), h.updateSetting.call(this, e, i) }, setSpeedMenu() { if (!l.element(this.elements.settings.panels.speed)) return const e = 'speed', i = this.elements.settings.panels.speed.querySelector('[role="menu"]') this.options.speed = this.options.speed.filter( s => s >= this.minimumSpeed && s <= this.maximumSpeed ) const t = !l.empty(this.options.speed) && this.options.speed.length > 1 h.toggleMenuButton.call(this, e, t), me(i), h.checkMenu.call(this), t && (this.options.speed.forEach(s => { h.createMenuItem.call(this, { value: s, list: i, type: e, title: h.getLabel.call(this, 'speed', s) }) }), h.updateSetting.call(this, e, i)) }, checkMenu() { const { buttons: e } = this.elements.settings, i = !l.empty(e) && Object.values(e).some(t => !t.hidden) J(this.elements.settings.menu, !i) }, focusFirstMenuItem(e, i = !1) { if (this.elements.settings.popup.hidden) return let t = e l.element(t) || (t = Object.values(this.elements.settings.panels).find(n => !n.hidden)) const s = t.querySelector('[role^="menuitem"]') Ee.call(this, s, i) }, toggleMenu(e) { const { popup: i } = this.elements.settings, t = this.elements.buttons.settings if (!l.element(i) || !l.element(t)) return const { hidden: s } = i let n = s if (l.boolean(e)) n = e else if (l.keyboardEvent(e) && e.key === 'Escape') n = !1 else if (l.event(e)) { const a = l.function(e.composedPath) ? e.composedPath()[0] : e.target, r = i.contains(a) if (r || (!r && e.target !== t && n)) return } t.setAttribute('aria-expanded', n), J(i, !n), A(this.elements.container, this.config.classNames.menu.open, n), n && l.keyboardEvent(e) ? h.focusFirstMenuItem.call(this, null, !0) : n || s || Ee.call(this, t, l.keyboardEvent(e)) }, getMenuSize(e) { const i = e.cloneNode(!0) ;(i.style.position = 'absolute'), (i.style.opacity = 0), i.removeAttribute('hidden'), e.parentNode.appendChild(i) const t = i.scrollWidth, s = i.scrollHeight return z(i), { width: t, height: s } }, showMenuPanel(e = '', i = !1) { const t = this.elements.container.querySelector( `#plyr-settings-${this.id}-${e}` ) if (!l.element(t)) return const s = t.parentNode, n = Array.from(s.children).find(a => !a.hidden) if (x.transitions && !x.reducedMotion) { ;(s.style.width = `${n.scrollWidth}px`), (s.style.height = `${n.scrollHeight}px`) const a = h.getMenuSize.call(this, t), r = o => { o.target === s && ['width', 'height'].includes(o.propertyName) && ((s.style.width = ''), (s.style.height = ''), fe.call(this, s, Ce, r)) } C.call(this, s, Ce, r), (s.style.width = `${a.width}px`), (s.style.height = `${a.height}px`) } J(n, !0), J(t, !1), h.focusFirstMenuItem.call(this, t, i) }, setDownloadUrl() { const e = this.elements.buttons.download l.element(e) && e.setAttribute('href', this.download) }, create(e) { const { bindMenuItemShortcuts: i, createButton: t, createProgress: s, createRange: n, createTime: a, setQualityMenu: r, setSpeedMenu: o, showMenuPanel: c } = h ;(this.elements.controls = null), l.array(this.config.controls) && this.config.controls.includes('play-large') && this.elements.container.appendChild(t.call(this, 'play-large')) const u = y('div', H(this.config.selectors.controls.wrapper)) this.elements.controls = u const p = { class: 'plyr__controls__item' } return ( Ne(l.array(this.config.controls) ? this.config.controls : []).forEach( f => { if ( (f === 'restart' && u.appendChild(t.call(this, 'restart', p)), f === 'rewind' && u.appendChild(t.call(this, 'rewind', p)), f === 'play' && u.appendChild(t.call(this, 'play', p)), f === 'fast-forward' && u.appendChild(t.call(this, 'fast-forward', p)), f === 'progress') ) { const d = y('div', { class: `${p.class} plyr__progress__container` }), v = y('div', H(this.config.selectors.progress)) if ( (v.appendChild(n.call(this, 'seek', { id: `plyr-seek-${e.id}` })), v.appendChild(s.call(this, 'buffer')), this.config.tooltips.seek) ) { const T = y( 'span', { class: this.config.classNames.tooltip }, '00:00' ) v.appendChild(T), (this.elements.display.seekTooltip = T) } ;(this.elements.progress = v), d.appendChild(this.elements.progress), u.appendChild(d) } if ( (f === 'current-time' && u.appendChild(a.call(this, 'currentTime', p)), f === 'duration' && u.appendChild(a.call(this, 'duration', p)), f === 'mute' || f === 'volume') ) { let { volume: d } = this.elements if ( ((l.element(d) && u.contains(d)) || ((d = y( 'div', I({}, p, { class: `${p.class} plyr__volume`.trim() }) )), (this.elements.volume = d), u.appendChild(d)), f === 'mute' && d.appendChild(t.call(this, 'mute')), f === 'volume' && !_.isIos) ) { const v = { max: 1, step: 0.05, value: this.config.volume } d.appendChild( n.call(this, 'volume', I(v, { id: `plyr-volume-${e.id}` })) ) } } if ( (f === 'captions' && u.appendChild(t.call(this, 'captions', p)), f === 'settings' && !l.empty(this.config.settings)) ) { const d = y( 'div', I({}, p, { class: `${p.class} plyr__menu`.trim(), hidden: '' }) ) d.appendChild( t.call(this, 'settings', { 'aria-haspopup': !0, 'aria-controls': `plyr-settings-${e.id}`, 'aria-expanded': !1 }) ) const v = y('div', { class: 'plyr__menu__container', id: `plyr-settings-${e.id}`, hidden: '' }), T = y('div'), k = y('div', { id: `plyr-settings-${e.id}-home` }), N = y('div', { role: 'menu' }) k.appendChild(N), T.appendChild(k), (this.elements.settings.panels.home = k), this.config.settings.forEach(w => { const M = y( 'button', I(H(this.config.selectors.buttons.settings), { type: 'button', class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`, role: 'menuitem', 'aria-haspopup': !0, hidden: '' }) ) i.call(this, M, w), C.call(this, M, 'click', () => { c.call(this, w, !1) }) const g = y('span', null, $.get(w, this.config)), S = y('span', { class: this.config.classNames.menu.value }) ;(S.innerHTML = e[w]), g.appendChild(S), M.appendChild(g), N.appendChild(M) const L = y('div', { id: `plyr-settings-${e.id}-${w}`, hidden: '' }), D = y('button', { type: 'button', class: `${this.config.classNames.control} ${this.config.classNames.control}--back` }) D.appendChild( y('span', { 'aria-hidden': !0 }, $.get(w, this.config)) ), D.appendChild( y( 'span', { class: this.config.classNames.hidden }, $.get('menuBack', this.config) ) ), C.call( this, L, 'keydown', W => { W.key === 'ArrowLeft' && (W.preventDefault(), W.stopPropagation(), c.call(this, 'home', !0)) }, !1 ), C.call(this, D, 'click', () => { c.call(this, 'home', !1) }), L.appendChild(D), L.appendChild(y('div', { role: 'menu' })), T.appendChild(L), (this.elements.settings.buttons[w] = M), (this.elements.settings.panels[w] = L) }), v.appendChild(T), d.appendChild(v), u.appendChild(d), (this.elements.settings.popup = v), (this.elements.settings.menu = d) } if ( (f === 'pip' && x.pip && u.appendChild(t.call(this, 'pip', p)), f === 'airplay' && x.airplay && u.appendChild(t.call(this, 'airplay', p)), f === 'download') ) { const d = I({}, p, { element: 'a', href: this.download, target: '_blank' }) this.isHTML5 && (d.download = '') const { download: v } = this.config.urls !l.url(v) && this.isEmbed && I(d, { icon: `logo-${this.provider}`, label: this.provider }), u.appendChild(t.call(this, 'download', d)) } f === 'fullscreen' && u.appendChild(t.call(this, 'fullscreen', p)) } ), this.isHTML5 && r.call(this, K.getQualityOptions.call(this)), o.call(this), u ) }, inject() { if (this.config.loadSprite) { const n = h.getIconUrl.call(this) n.cors && ft(n.url, 'sprite-plyr') } this.id = Math.floor(1e4 * Math.random()) let e = null this.elements.controls = null const i = { id: this.id, seektime: this.config.seekTime, title: this.config.title } let t = !0 l.function(this.config.controls) && (this.config.controls = this.config.controls.call(this, i)), this.config.controls || (this.config.controls = []), l.element(this.config.controls) || l.string(this.config.controls) ? (e = this.config.controls) : ((e = h.create.call(this, { id: this.id, seektime: this.config.seekTime, speed: this.speed, quality: this.quality, captions: E.getLabel.call(this) })), (t = !1)) let s if ( (t && l.string(this.config.controls) && (e = (n => { let a = n return ( Object.entries(i).forEach(([r, o]) => { a = ne(a, `{${r}}`, o) }), a ) })(e)), l.string(this.config.selectors.controls.container) && (s = document.querySelector(this.config.selectors.controls.container)), l.element(s) || (s = this.elements.container), s[l.element(e) ? 'insertAdjacentElement' : 'insertAdjacentHTML']( 'afterbegin', e ), l.element(this.elements.controls) || h.findElements.call(this), !l.empty(this.elements.buttons)) ) { const n = a => { const r = this.config.classNames.controlPressed Object.defineProperty(a, 'pressed', { enumerable: !0, get: () => ge(a, r), set(o = !1) { A(a, r, o) } }) } Object.values(this.elements.buttons) .filter(Boolean) .forEach(a => { l.array(a) || l.nodeList(a) ? Array.from(a).filter(Boolean).forEach(n) : n(a) }) } if ((_.isEdge && nt(s), this.config.tooltips.controls)) { const { classNames: n, selectors: a } = this.config, r = `${a.controls.wrapper} ${a.labels} .${n.hidden}`, o = Z.call(this, r) Array.from(o).forEach(c => { A(c, this.config.classNames.hidden, !1), A(c, this.config.classNames.tooltip, !0) }) } }, setMediaMetadata() { try { 'mediaSession' in navigator && (navigator.mediaSession.metadata = new window.MediaMetadata({ title: this.config.mediaMetadata.title, artist: this.config.mediaMetadata.artist, album: this.config.mediaMetadata.album, artwork: this.config.mediaMetadata.artwork })) } catch {} }, setMarkers() { var e, i if (!this.duration || this.elements.markers) return const t = (e = this.config.markers) === null || e === void 0 || (i = e.points) === null || i === void 0 ? void 0 : i.filter(({ time: c }) => c > 0 && c < this.duration) if (t == null || !t.length) return const s = document.createDocumentFragment(), n = document.createDocumentFragment() let a = null const r = `${this.config.classNames.tooltip}--visible`, o = c => A(a, r, c) t.forEach(c => { const u = y('span', { class: this.config.classNames.marker }, ''), p = (c.time / this.duration) * 100 + '%' a && (u.addEventListener('mouseenter', () => { c.label || ((a.style.left = p), (a.innerHTML = c.label), o(!0)) }), u.addEventListener('mouseleave', () => { o(!1) })), u.addEventListener('click', () => { this.currentTime = c.time }), (u.style.left = p), n.appendChild(u) }), s.appendChild(n), this.config.tooltips.seek || ((a = y('span', { class: this.config.classNames.tooltip }, '')), s.appendChild(a)), (this.elements.markers = { points: n, tip: a }), this.elements.progress.appendChild(s) } } function bt(e, i = !0) { let t = e if (i) { const s = document.createElement('a') ;(s.href = t), (t = s.href) } try { return new URL(t) } catch { return null } } function vt(e) { const i = new URLSearchParams() return ( l.object(e) && Object.entries(e).forEach(([t, s]) => { i.set(t, s) }), i ) } const E = { setup() { if (!this.supported.ui) return if (!this.isVideo || this.isYouTube || (this.isHTML5 && !x.textTracks)) return void ( l.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions') && h.setCaptionsMenu.call(this) ) if ( (l.element(this.elements.captions) || ((this.elements.captions = y( 'div', H(this.config.selectors.captions) )), gi(this.elements.captions, this.elements.wrapper)), _.isIE && window.URL) ) { const s = this.media.querySelectorAll('track') Array.from(s).forEach(n => { const a = n.getAttribute('src'), r = bt(a) r !== null && r.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(r.protocol) && le(a, 'blob') .then(o => { n.setAttribute('src', window.URL.createObjectURL(o)) }) .catch(() => { z(n) }) }) } const e = Ne( ( navigator.languages || [ navigator.language || navigator.userLanguage || 'en' ] ).map(s => s.split('-')[0]) ) let i = ( this.storage.get('language') || this.config.captions.language || 'auto' ).toLowerCase() i === 'auto' && ([i] = e) let t = this.storage.get('captions') if ( (l.boolean(t) || ({ active: t } = this.config.captions), Object.assign(this.captions, { toggled: !1, active: t, language: i, languages: e }), this.isHTML5) ) { const s = this.config.captions.update ? 'addtrack removetrack' : 'removetrack' C.call(this, this.media.textTracks, s, E.update.bind(this)) } setTimeout(E.update.bind(this), 0) }, update() { const e = E.getTracks.call(this, !0), { active: i, language: t, meta: s, currentTrackNode: n } = this.captions, a = Boolean(e.find(r => r.language === t)) this.isHTML5 && this.isVideo && e .filter(r => !s.get(r)) .forEach(r => { this.debug.log('Track added', r), s.set(r, { default: r.mode === 'showing' }), r.mode === 'showing' && (r.mode = 'hidden'), C.call(this, r, 'cuechange', () => E.updateCues.call(this)) }), ((a && this.language !== t) || !e.includes(n)) && (E.setLanguage.call(this, t), E.toggle.call(this, i && a)), this.elements && A( this.elements.container, this.config.classNames.captions.enabled, !l.empty(e) ), l.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions') && h.setCaptionsMenu.call(this) }, toggle(e, i = !0) { if (!this.supported.ui) return const { toggled: t } = this.captions, s = this.config.classNames.captions.active, n = l.nullOrUndefined(e) ? !t : e if (n !== t) { if ( (i || ((this.captions.active = n), this.storage.set({ captions: n })), !this.language && n && !i) ) { const a = E.getTracks.call(this), r = E.findTrack.call( this, [this.captions.language, ...this.captions.languages], !0 ) return ( (this.captions.language = r.language), void E.set.call(this, a.indexOf(r)) ) } this.elements.buttons.captions && (this.elements.buttons.captions.pressed = n), A(this.elements.container, s, n), (this.captions.toggled = n), h.updateSetting.call(this, 'captions'), b.call(this, this.media, n ? 'captionsenabled' : 'captionsdisabled') } setTimeout(() => { n && this.captions.toggled && (this.captions.currentTrackNode.mode = 'hidden') }) }, set(e, i = !0) { const t = E.getTracks.call(this) if (e !== -1) if (l.number(e)) if (e in t) { if (this.captions.currentTrack !== e) { this.captions.currentTrack = e const s = t[e], { language: n } = s || {} ;(this.captions.currentTrackNode = s), h.updateSetting.call(this, 'captions'), i || ((this.captions.language = n), this.storage.set({ language: n })), this.isVimeo && this.embed.enableTextTrack(n), b.call(this, this.media, 'languagechange') } E.toggle.call(this, !0, i), this.isHTML5 && this.isVideo && E.updateCues.call(this) } else this.debug.warn('Track not found', e) else this.debug.warn('Invalid caption argument', e) else E.toggle.call(this, !1, i) }, setLanguage(e, i = !0) { if (!l.string(e)) return void this.debug.warn('Invalid language argument', e) const t = e.toLowerCase() this.captions.language = t const s = E.getTracks.call(this), n = E.findTrack.call(this, [t]) E.set.call(this, s.indexOf(n), i) }, getTracks(e = !1) { return Array.from((this.media || {}).textTracks || []) .filter(i => !this.isHTML5 || e || this.captions.meta.has(i)) .filter(i => ['captions', 'subtitles'].includes(i.kind)) }, findTrack(e, i = !1) { const t = E.getTracks.call(this), s = r => Number((this.captions.meta.get(r) || {}).default), n = Array.from(t).sort((r, o) => s(o) - s(r)) let a return ( e.every(r => ((a = n.find(o => o.language === r)), !a)), a || (i ? n[0] : void 0) ) }, getCurrentTrack() { return E.getTracks.call(this)[this.currentTrack] }, getLabel(e) { let i = e return ( !l.track(i) && x.textTracks && this.captions.toggled && (i = E.getCurrentTrack.call(this)), l.track(i) ? l.empty(i.label) ? l.empty(i.language) ? $.get('enabled', this.config) : e.language.toUpperCase() : i.label : $.get('disabled', this.config) ) }, updateCues(e) { if (!this.supported.ui) return if (!l.element(this.elements.captions)) return void this.debug.warn('No captions element to render to') if (!l.nullOrUndefined(e) && !Array.isArray(e)) return void this.debug.warn('updateCues: Invalid input', e) let i = e if (!i) { const s = E.getCurrentTrack.call(this) i = Array.from((s || {}).activeCues || []) .map(n => n.getCueAsHTML()) .map(Ei) } const t = i.map(s => s.trim()).join(` `) if (t !== this.elements.captions.innerHTML) { me(this.elements.captions) const s = y('span', H(this.config.selectors.caption)) ;(s.innerHTML = t), this.elements.captions.appendChild(s), b.call(this, this.media, 'cuechange') } } }, wt = { enabled: !0, title: '', debug: !1, autoplay: !1, autopause: !0, playsinline: !0, seekTime: 10, volume: 1, muted: !1, duration: null, displayDuration: !0, invertTime: !0, toggleInvert: !0, ratio: null, clickToPlay: !0, hideControls: !0, resetOnEnd: !1, disableContextMenu: !0, loadSprite: !0, iconPrefix: 'plyr', iconUrl: 'https://cdn.plyr.io/3.7.2/plyr.svg', blankVideo: 'https://cdn.plyr.io/static/blank.mp4', quality: { default: 576, options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240], forced: !1, onChange: null }, loop: { active: !1 }, speed: { selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4] }, keyboard: { focused: !0, global: !1 }, tooltips: { controls: !1, seek: !0 }, captions: { active: !1, language: 'auto', update: !1 }, fullscreen: { enabled: !0, fallback: !0, iosNative: !1 }, storage: { enabled: !0, key: 'plyr' }, controls: [ 'play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen' ], settings: ['captions', 'quality', 'speed'], i18n: { restart: 'Restart', rewind: 'Rewind {seektime}s', play: 'Play', pause: 'Pause', fastForward: 'Forward {seektime}s', seek: 'Seek', seekLabel: '{currentTime} of {duration}', played: 'Played', buffered: 'Buffered', currentTime: 'Current time', duration: 'Duration', volume: 'Volume', mute: 'Mute', unmute: 'Unmute', enableCaptions: 'Enable captions', disableCaptions: 'Disable captions', download: 'Download', enterFullscreen: 'Enter fullscreen', exitFullscreen: 'Exit fullscreen', frameTitle: 'Player for {title}', captions: 'Captions', settings: 'Settings', pip: 'PIP', menuBack: 'Go back to previous menu', speed: 'Speed', normal: 'Normal', quality: 'Quality', loop: 'Loop', start: 'Start', end: 'End', all: 'All', reset: 'Reset', disabled: 'Disabled', enabled: 'Enabled', advertisement: 'Ad', qualityBadge: { 2160: '4K', 1440: 'HD', 1080: 'HD', 720: 'HD', 576: 'SD', 480: 'SD' } }, urls: { download: null, vimeo: { sdk: 'https://player.vimeo.com/api/player.js', iframe: 'https://player.vimeo.com/video/{0}?{1}', api: 'https://vimeo.com/api/oembed.json?url={0}' }, youtube: { sdk: 'https://www.youtube.com/iframe_api', api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}' }, googleIMA: { sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js' } }, listeners: { seek: null, play: null, pause: null, restart: null, rewind: null, fastForward: null, mute: null, volume: null, captions: null, download: null, fullscreen: null, pip: null, airplay: null, speed: null, quality: null, loop: null, language: null }, events: [ 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange', 'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready', 'statechange', 'qualitychange', 'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick' ], selectors: { editable: 'input, textarea, select, [contenteditable]', container: '.plyr', controls: { container: null, wrapper: '.plyr__controls' }, labels: '[data-plyr]', buttons: { play: '[data-plyr="play"]', pause: '[data-plyr="pause"]', restart: '[data-plyr="restart"]', rewind: '[data-plyr="rewind"]', fastForward: '[data-plyr="fast-forward"]', mute: '[data-plyr="mute"]', captions: '[data-plyr="captions"]', download: '[data-plyr="download"]', fullscreen: '[data-plyr="fullscreen"]', pip: '[data-plyr="pip"]', airplay: '[data-plyr="airplay"]', settings: '[data-plyr="settings"]', loop: '[data-plyr="loop"]' }, inputs: { seek: '[data-plyr="seek"]', volume: '[data-plyr="volume"]', speed: '[data-plyr="speed"]', language: '[data-plyr="language"]', quality: '[data-plyr="quality"]' }, display: { currentTime: '.plyr__time--current', duration: '.plyr__time--duration', buffer: '.plyr__progress__buffer', loop: '.plyr__progress__loop', volume: '.plyr__volume--display' }, progress: '.plyr__progress', captions: '.plyr__captions', caption: '.plyr__caption' }, classNames: { type: 'plyr--{0}', provider: 'plyr--{0}', video: 'plyr__video-wrapper', embed: 'plyr__video-embed', videoFixedRatio: 'plyr__video-wrapper--fixed-ratio', embedContainer: 'plyr__video-embed__container', poster: 'plyr__poster', posterEnabled: 'plyr__poster-enabled', ads: 'plyr__ads', control: 'plyr__control', controlPressed: 'plyr__control--pressed', playing: 'plyr--playing', paused: 'plyr--paused', stopped: 'plyr--stopped', loading: 'plyr--loading', hover: 'plyr--hover', tooltip: 'plyr__tooltip', cues: 'plyr__cues', marker: 'plyr__progress__marker', hidden: 'plyr__sr-only', hideControls: 'plyr--hide-controls', isIos: 'plyr--is-ios', isTouch: 'plyr--is-touch', uiSupported: 'plyr--full-ui', noTransition: 'plyr--no-transition', display: { time: 'plyr__time' }, menu: { value: 'plyr__menu__value', badge: 'plyr__badge', open: 'plyr--menu-open' }, captions: { enabled: 'plyr--captions-enabled', active: 'plyr--captions-active' }, fullscreen: { enabled: 'plyr--fullscreen-enabled', fallback: 'plyr--fullscreen-fallback' }, pip: { supported: 'plyr--pip-supported', active: 'plyr--pip-active' }, airplay: { supported: 'plyr--airplay-supported', active: 'plyr--airplay-active' }, tabFocus: 'plyr__tab-focus', previewThumbnails: { thumbContainer: 'plyr__preview-thumb', thumbContainerShown: 'plyr__preview-thumb--is-shown', imageContainer: 'plyr__preview-thumb__image-container', timeContainer: 'plyr__preview-thumb__time-container', scrubbingContainer: 'plyr__preview-scrubbing', scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown' } }, attributes: { embed: { provider: 'data-plyr-provider', id: 'data-plyr-embed-id', hash: 'data-plyr-embed-hash' } }, ads: { enabled: !1, publisherId: '', tagUrl: '' }, previewThumbnails: { enabled: !1, src: '' }, vimeo: { byline: !1, portrait: !1, title: !1, speed: !0, transparent: !1, customControls: !0, referrerPolicy: null, premium: !1 }, youtube: { rel: 0, showinfo: 0, iv_load_policy: 3, modestbranding: 1, customControls: !0, noCookie: !1 }, mediaMetadata: { title: '', artist: '', album: '', artwork: [] }, markers: { enabled: !1, points: [] } }, Ie = { active: 'picture-in-picture', inactive: 'inline' }, Y = { html5: 'html5', youtube: 'youtube', vimeo: 'vimeo' }, Le = { audio: 'audio', video: 'video' } function Ni(e) { return /^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test( e ) ? Y.youtube : /^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(e) ? Y.vimeo : null } const Oe = () => {} class Mi { constructor(i = !1) { ;(this.enabled = window.console && i), this.enabled && this.log('Debugging enabled') } get log() { return this.enabled ? Function.prototype.bind.call(console.log, console) : Oe } get warn() { return this.enabled ? Function.prototype.bind.call(console.warn, console) : Oe } get error() { return this.enabled ? Function.prototype.bind.call(console.error, console) : Oe } } class F { constructor(i) { m(this, 'onChange', () => { if (!this.enabled) return const t = this.player.elements.buttons.fullscreen l.element(t) && (t.pressed = this.active) const s = this.target === this.player.media ? this.target : this.player.elements.container b.call( this.player, s, this.active ? 'enterfullscreen' : 'exitfullscreen', !0 ) }), m(this, 'toggleFallback', (t = !1) => { if ( (t ? (this.scrollPosition = { x: window.scrollX || 0, y: window.scrollY || 0 }) : window.scrollTo(this.scrollPosition.x, this.scrollPosition.y), (document.body.style.overflow = t ? 'hidden' : ''), A(this.target, this.player.config.classNames.fullscreen.fallback, t), _.isIos) ) { let s = document.head.querySelector('meta[name="viewport"]') const n = 'viewport-fit=cover' s || ((s = document.createElement('meta')), s.setAttribute('name', 'viewport')) const a = l.string(s.content) && s.content.includes(n) t ? ((this.cleanupViewport = !a), a || (s.content += `,${n}`)) : this.cleanupViewport && (s.content = s.content .split(',') .filter(r => r.trim() !== n) .join(',')) } this.onChange() }), m(this, 'trapFocus', t => { if (_.isIos || !this.active || t.key !== 'Tab') return const s = document.activeElement, n = Z.call( this.player, 'a[href], button:not(:disabled), input:not(:disabled), [tabindex]' ), [a] = n, r = n[n.length - 1] s !== r || t.shiftKey ? s === a && t.shiftKey && (r.focus(), t.preventDefault()) : (a.focus(), t.preventDefault()) }), m(this, 'update', () => { if (this.enabled) { let t ;(t = this.forceFallback ? 'Fallback (forced)' : F.native ? 'Native' : 'Fallback'), this.player.debug.log(`${t} fullscreen enabled`) } else this.player.debug.log( 'Fullscreen not supported and fallback disabled' ) A( this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled ) }), m(this, 'enter', () => { this.enabled && (_.isIos && this.player.config.fullscreen.iosNative ? this.player.isVimeo ? this.player.embed.requestFullscreen() : this.target.webkitEnterFullscreen() : !F.native || this.forceFallback ? this.toggleFallback(!0) : this.prefix ? l.empty(this.prefix) || this.target[`${this.prefix}Request${this.property}`]() : this.target.requestFullscreen({ navigationUI: 'hide' })) }), m(this, 'exit', () => { if (this.enabled) if (_.isIos && this.player.config.fullscreen.iosNative) this.target.webkitExitFullscreen(), V(this.player.play()) else if (!F.native || this.forceFallback) this.toggleFallback(!1) else if (this.prefix) { if (!l.empty(this.prefix)) { const t = this.prefix === 'moz' ? 'Cancel' : 'Exit' document[`${this.prefix}${t}${this.property}`]() } } else (document.cancelFullScreen || document.exitFullscreen).call( document ) }), m(this, 'toggle', () => { this.active ? this.exit() : this.enter() }), (this.player = i), (this.prefix = F.prefix), (this.property = F.property), (this.scrollPosition = { x: 0, y: 0 }), (this.forceFallback = i.config.fullscreen.fallback === 'force'), (this.player.elements.fullscreen = i.config.fullscreen.container && fi(this.player.elements.container, i.config.fullscreen.container)), C.call( this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => { this.onChange() } ), C.call(this.player, this.player.elements.container, 'dblclick', t => { ;(l.element(this.player.elements.controls) && this.player.elements.controls.contains(t.target)) || this.player.listeners.proxy(t, this.toggle, 'fullscreen') }), C.call(this, this.player.elements.container, 'keydown', t => this.trapFocus(t) ), this.update() } static get native() { return !!( document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled ) } get usingNative() { return F.native && !this.forceFallback } static get prefix() { if (l.function(document.exitFullscreen)) return '' let i = '' return ( ['webkit', 'moz', 'ms'].some( t => !( !l.function(document[`${t}ExitFullscreen`]) && !l.function(document[`${t}CancelFullScreen`]) ) && ((i = t), !0) ), i ) } static get property() { return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen' } get enabled() { return ( (F.native || this.player.config.fullscreen.fallback) && this.player.config.fullscreen.enabled && this.player.supported.ui && this.player.isVideo ) } get active() { if (!this.enabled) return !1 if (!F.native || this.forceFallback) return ge(this.target, this.player.config.classNames.fullscreen.fallback) const i = this.prefix ? this.target.getRootNode()[`${this.prefix}${this.property}Element`] : this.target.getRootNode().fullscreenElement return i && i.shadowRoot ? i === this.target.getRootNode().host : i === this.target } get target() { return _.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.fullscreen || this.player.elements.container } } function ve(e, i = 1) { return new Promise((t, s) => { const n = new Image(), a = () => { delete n.onload, delete n.onerror, (n.naturalWidth >= i ? t : s)(n) } Object.assign(n, { onload: a, onerror: a, src: e }) }) } const P = { addStyleHook() { A( this.elements.container, this.config.selectors.container.replace('.', ''), !0 ), A( this.elements.container, this.config.classNames.uiSupported, this.supported.ui ) }, toggleNativeControls(e = !1) { e && this.isHTML5 ? this.media.setAttribute('controls', '') : this.media.removeAttribute('controls') }, build() { if ((this.listeners.media(), !this.supported.ui)) return ( this.debug.warn(`Basic support only for ${this.provider} ${this.type}`), void P.toggleNativeControls.call(this, !0) ) l.element(this.elements.controls) || (h.inject.call(this), this.listeners.controls()), P.toggleNativeControls.call(this), this.isHTML5 && E.setup.call(this), (this.volume = null), (this.muted = null), (this.loop = null), (this.quality = null), (this.speed = null), h.updateVolume.call(this), h.timeUpdate.call(this), h.durationUpdate.call(this), P.checkPlaying.call(this), A( this.elements.container, this.config.classNames.pip.supported, x.pip && this.isHTML5 && this.isVideo ), A( this.elements.container, this.config.classNames.airplay.supported, x.airplay && this.isHTML5 ), A(this.elements.container, this.config.classNames.isIos, _.isIos), A(this.elements.container, this.config.classNames.isTouch, this.touch), (this.ready = !0), setTimeout(() => { b.call(this, this.media, 'ready') }, 0), P.setTitle.call(this), this.poster && P.setPoster.call(this, this.poster, !1).catch(() => {}), this.config.duration && h.durationUpdate.call(this), this.config.mediaMetadata && h.setMediaMetadata.call(this) }, setTitle() { let e = $.get('play', this.config) if ( (l.string(this.config.title) && !l.empty(this.config.title) && (e += `, ${this.config.title}`), Array.from(this.elements.buttons.play || []).forEach(i => { i.setAttribute('aria-label', e) }), this.isEmbed) ) { const i = O.call(this, 'iframe') if (!l.element(i)) return const t = l.empty(this.config.title) ? 'video' : this.config.title, s = $.get('frameTitle', this.config) i.setAttribute('title', s.replace('{title}', t)) } }, togglePoster(e) { A(this.elements.container, this.config.classNames.posterEnabled, e) }, setPoster(e, i = !0) { return i && this.poster ? Promise.reject(new Error('Poster already set')) : (this.media.setAttribute('data-poster', e), this.elements.poster.removeAttribute('hidden'), vi .call(this) .then(() => ve(e)) .catch(t => { throw (e === this.poster && P.togglePoster.call(this, !1), t) }) .then(() => { if (e !== this.poster) throw new Error('setPoster cancelled by later call to setPoster') }) .then( () => ( Object.assign(this.elements.poster.style, { backgroundImage: `url('${e}')`, backgroundSize: '' }), P.togglePoster.call(this, !0), e ) )) }, checkPlaying(e) { A(this.elements.container, this.config.classNames.playing, this.playing), A(this.elements.container, this.config.classNames.paused, this.paused), A(this.elements.container, this.config.classNames.stopped, this.stopped), Array.from(this.elements.buttons.play || []).forEach(i => { Object.assign(i, { pressed: this.playing }), i.setAttribute( 'aria-label', $.get(this.playing ? 'pause' : 'play', this.config) ) }), (l.event(e) && e.type === 'timeupdate') || P.toggleControls.call(this) }, checkLoading(e) { ;(this.loading = ['stalled', 'waiting'].includes(e.type)), clearTimeout(this.timers.loading), (this.timers.loading = setTimeout( () => { A( this.elements.container, this.config.classNames.loading, this.loading ), P.toggleControls.call(this) }, this.loading ? 250 : 0 )) }, toggleControls(e) { const { controls: i } = this.elements if (i && this.config.hideControls) { const t = this.touch && this.lastSeekTime + 2e3 > Date.now() this.toggleControls( Boolean(e || this.loading || this.paused || i.pressed || i.hover || t) ) } }, migrateStyles() { Object.values(q({}, this.media.style)) .filter(e => !l.empty(e) && l.string(e) && e.startsWith('--plyr')) .forEach(e => { this.elements.container.style.setProperty( e, this.media.style.getPropertyValue(e) ), this.media.style.removeProperty(e) }), l.empty(this.media.style) && this.media.removeAttribute('style') } } class xi { constructor(i) { m(this, 'firstTouch', () => { const { player: t } = this, { elements: s } = t ;(t.touch = !0), A(s.container, t.config.classNames.isTouch, !0) }), m(this, 'setTabFocus', t => { const { player: s } = this, { elements: n } = s, { key: a, type: r, timeStamp: o } = t if ((clearTimeout(this.focusTimer), r === 'keydown' && a !== 'Tab')) return r === 'keydown' && (this.lastKeyDown = o) const c = o - this.lastKeyDown <= 20 ;(r !== 'focus' || c) && ((() => { const u = s.config.classNames.tabFocus A(Z.call(s, `.${u}`), u, !1) })(), r !== 'focusout' && (this.focusTimer = setTimeout(() => { const u = document.activeElement n.container.contains(u) && A(document.activeElement, s.config.classNames.tabFocus, !0) }, 10))) }), m(this, 'global', (t = !0) => { const { player: s } = this s.config.keyboard.global && ee.call(s, window, 'keydown keyup', this.handleKey, t, !1), ee.call(s, document.body, 'click', this.toggleMenu, t), Pe.call(s, document.body, 'touchstart', this.firstTouch), ee.call( s, document.body, 'keydown focus blur focusout', this.setTabFocus, t, !1, !0 ) }), m(this, 'container', () => { const { player: t } = this, { config: s, elements: n, timers: a } = t !s.keyboard.global && s.keyboard.focused && C.call(t, n.container, 'keydown keyup', this.handleKey, !1), C.call( t, n.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', c => { const { controls: u } = n u && c.type === 'enterfullscreen' && ((u.pressed = !1), (u.hover = !1)) let p = 0 ;['touchstart', 'touchmove', 'mousemove'].includes(c.type) && (P.toggleControls.call(t, !0), (p = t.touch ? 3e3 : 2e3)), clearTimeout(a.controls), (a.controls = setTimeout(() => P.toggleControls.call(t, !1), p)) } ) const r = () => { if (!t.isVimeo || t.config.vimeo.premium) return const c = n.wrapper, { active: u } = t.fullscreen, [p, f] = Me.call(t), d = ut(`aspect-ratio: ${p} / ${f}`) if (!u) return void (d ? ((c.style.width = null), (c.style.height = null)) : ((c.style.maxWidth = null), (c.style.margin = null))) const [v, T] = wi(), k = v / T > p / f d ? ((c.style.width = k ? 'auto' : '100%'), (c.style.height = k ? '100%' : 'auto')) : ((c.style.maxWidth = k ? (T / f) * p + 'px' : null), (c.style.margin = k ? '0 auto' : null)) }, o = () => { clearTimeout(a.resized), (a.resized = setTimeout(r, 50)) } C.call(t, n.container, 'enterfullscreen exitfullscreen', c => { const { target: u } = t.fullscreen u === n.container && ((!t.isEmbed && l.empty(t.config.ratio)) || (r(), (c.type === 'enterfullscreen' ? C : fe).call( t, window, 'resize', o ))) }) }), m(this, 'media', () => { const { player: t } = this, { elements: s } = t if ( (C.call(t, t.media, 'timeupdate seeking seeked', a => h.timeUpdate.call(t, a) ), C.call(t, t.media, 'durationchange loadeddata loadedmetadata', a => h.durationUpdate.call(t, a) ), C.call(t, t.media, 'ended', () => { t.isHTML5 && t.isVideo && t.config.resetOnEnd && (t.restart(), t.pause()) }), C.call(t, t.media, 'progress playing seeking seeked', a => h.updateProgress.call(t, a) ), C.call(t, t.media, 'volumechange', a => h.updateVolume.call(t, a)), C.call(t, t.media, 'playing play pause ended emptied timeupdate', a => P.checkPlaying.call(t, a) ), C.call(t, t.media, 'waiting canplay seeked playing', a => P.checkLoading.call(t, a) ), t.supported.ui && t.config.clickToPlay && !t.isAudio) ) { const a = O.call(t, `.${t.config.classNames.video}`) if (!l.element(a)) return C.call(t, s.container, 'click', r => { ;([s.container, a].includes(r.target) || a.contains(r.target)) && ((t.touch && t.config.hideControls) || (t.ended ? (this.proxy(r, t.restart, 'restart'), this.proxy( r, () => { V(t.play()) }, 'play' )) : this.proxy( r, () => { V(t.togglePlay()) }, 'play' ))) }) } t.supported.ui && t.config.disableContextMenu && C.call( t, s.wrapper, 'contextmenu', a => { a.preventDefault() }, !1 ), C.call(t, t.media, 'volumechange', () => { t.storage.set({ volume: t.volume, muted: t.muted }) }), C.call(t, t.media, 'ratechange', () => { h.updateSetting.call(t, 'speed'), t.storage.set({ speed: t.speed }) }), C.call(t, t.media, 'qualitychange', a => { h.updateSetting.call(t, 'quality', null, a.detail.quality) }), C.call(t, t.media, 'ready qualitychange', () => { h.setDownloadUrl.call(t) }) const n = t.config.events.concat(['keyup', 'keydown']).join(' ') C.call(t, t.media, n, a => { let { detail: r = {} } = a a.type === 'error' && (r = t.media.error), b.call(t, s.container, a.type, !0, r) }) }), m(this, 'proxy', (t, s, n) => { const { player: a } = this, r = a.config.listeners[n] let o = !0 l.function(r) && (o = r.call(a, t)), o !== !1 && l.function(s) && s.call(a, t) }), m(this, 'bind', (t, s, n, a, r = !0) => { const { player: o } = this, c = o.config.listeners[a], u = l.function(c) C.call(o, t, s, p => this.proxy(p, n, a), r && !u) }), m(this, 'controls', () => { const { player: t } = this, { elements: s } = t, n = _.isIE ? 'change' : 'input' if ( (s.buttons.play && Array.from(s.buttons.play).forEach(a => { this.bind( a, 'click', () => { V(t.togglePlay()) }, 'play' ) }), this.bind(s.buttons.restart, 'click', t.restart, 'restart'), this.bind( s.buttons.rewind, 'click', () => { ;(t.lastSeekTime = Date.now()), t.rewind() }, 'rewind' ), this.bind( s.buttons.fastForward, 'click', () => { ;(t.lastSeekTime = Date.now()), t.forward() }, 'fastForward' ), this.bind( s.buttons.mute, 'click', () => { t.muted = !t.muted }, 'mute' ), this.bind(s.buttons.captions, 'click', () => t.toggleCaptions()), this.bind( s.buttons.download, 'click', () => { b.call(t, t.media, 'download') }, 'download' ), this.bind( s.buttons.fullscreen, 'click', () => { t.fullscreen.toggle() }, 'fullscreen' ), this.bind( s.buttons.pip, 'click', () => { t.pip = 'toggle' }, 'pip' ), this.bind(s.buttons.airplay, 'click', t.airplay, 'airplay'), this.bind( s.buttons.settings, 'click', a => { a.stopPropagation(), a.preventDefault(), h.toggleMenu.call(t, a) }, null, !1 ), this.bind( s.buttons.settings, 'keyup', a => { ;['Space', 'Enter'].includes(a.key) && (a.key !== 'Enter' ? (a.preventDefault(), a.stopPropagation(), h.toggleMenu.call(t, a)) : h.focusFirstMenuItem.call(t, null, !0)) }, null, !1 ), this.bind(s.settings.menu, 'keydown', a => { a.key === 'Escape' && h.toggleMenu.call(t, a) }), this.bind(s.inputs.seek, 'mousedown mousemove', a => { const r = s.progress.getBoundingClientRect(), o = (100 / r.width) * (a.pageX - r.left) a.currentTarget.setAttribute('seek-value', o) }), this.bind( s.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', a => { const r = a.currentTarget, o = 'play-on-seeked' if ( l.keyboardEvent(a) && !['ArrowLeft', 'ArrowRight'].includes(a.key) ) return t.lastSeekTime = Date.now() const c = r.hasAttribute(o), u = ['mouseup', 'touchend', 'keyup'].includes(a.type) c && u ? (r.removeAttribute(o), V(t.play())) : !u && t.playing && (r.setAttribute(o, ''), t.pause()) } ), _.isIos) ) { const a = Z.call(t, 'input[type="range"]') Array.from(a).forEach(r => this.bind(r, n, o => nt(o.target))) } this.bind( s.inputs.seek, n, a => { const r = a.currentTarget let o = r.getAttribute('seek-value') l.empty(o) && (o = r.value), r.removeAttribute('seek-value'), (t.currentTime = (o / r.max) * t.duration) }, 'seek' ), this.bind(s.progress, 'mouseenter mouseleave mousemove', a => h.updateSeekTooltip.call(t, a) ), this.bind(s.progress, 'mousemove touchmove', a => { const { previewThumbnails: r } = t r && r.loaded && r.startMove(a) }), this.bind(s.progress, 'mouseleave touchend click', () => { const { previewThumbnails: a } = t a && a.loaded && a.endMove(!1, !0) }), this.bind(s.progress, 'mousedown touchstart', a => { const { previewThumbnails: r } = t r && r.loaded && r.startScrubbing(a) }), this.bind(s.progress, 'mouseup touchend', a => { const { previewThumbnails: r } = t r && r.loaded && r.endScrubbing(a) }), _.isWebkit && Array.from(Z.call(t, 'input[type="range"]')).forEach(a => { this.bind(a, 'input', r => h.updateRangeFill.call(t, r.target)) }), t.config.toggleInvert && !l.element(s.display.duration) && this.bind(s.display.currentTime, 'click', () => { t.currentTime !== 0 && ((t.config.invertTime = !t.config.invertTime), h.timeUpdate.call(t)) }), this.bind( s.inputs.volume, n, a => { t.volume = a.target.value }, 'volume' ), this.bind(s.controls, 'mouseenter mouseleave', a => { s.controls.hover = !t.touch && a.type === 'mouseenter' }), s.fullscreen && Array.from(s.fullscreen.children) .filter(a => !a.contains(s.container)) .forEach(a => { this.bind(a, 'mouseenter mouseleave', r => { s.controls && (s.controls.hover = !t.touch && r.type === 'mouseenter') }) }), this.bind( s.controls, 'mousedown mouseup touchstart touchend touchcancel', a => { s.controls.pressed = ['mousedown', 'touchstart'].includes(a.type) } ), this.bind(s.controls, 'focusin', () => { const { config: a, timers: r } = t A(s.controls, a.classNames.noTransition, !0), P.toggleControls.call(t, !0), setTimeout(() => { A(s.controls, a.classNames.noTransition, !1) }, 0) const o = this.touch ? 3e3 : 4e3 clearTimeout(r.controls), (r.controls = setTimeout(() => P.toggleControls.call(t, !1), o)) }), this.bind( s.inputs.volume, 'wheel', a => { const r = a.webkitDirectionInvertedFromDevice, [o, c] = [a.deltaX, -a.deltaY].map(f => (r ? -f : f)), u = Math.sign(Math.abs(o) > Math.abs(c) ? o : c) t.increaseVolume(u / 50) const { volume: p } = t.media ;((u === 1 && p < 1) || (u === -1 && p > 0)) && a.preventDefault() }, 'volume', !1 ) }), (this.player = i), (this.lastKey = null), (this.focusTimer = null), (this.lastKeyDown = null), (this.handleKey = this.handleKey.bind(this)), (this.toggleMenu = this.toggleMenu.bind(this)), (this.setTabFocus = this.setTabFocus.bind(this)), (this.firstTouch = this.firstTouch.bind(this)) } handleKey(i) { const { player: t } = this, { elements: s } = t, { key: n, type: a, altKey: r, ctrlKey: o, metaKey: c, shiftKey: u } = i, p = a === 'keydown', f = p && n === this.lastKey if (!(r || o || c || u) && !!n) { if (p) { const v = document.activeElement if (l.element(v)) { const { editable: T } = t.config.selectors, { seek: k } = s.inputs if ( (v !== k && Q(v, T)) || (i.key === 'Space' && Q(v, 'button, [role^="menuitem"]')) ) return } switch ( ([ 'Space', 'ArrowLeft', 'ArrowUp', 'ArrowRight', 'ArrowDown', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'c', 'f', 'k', 'l', 'm' ].includes(n) && (i.preventDefault(), i.stopPropagation()), n) ) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': f || ((d = parseInt(n, 10)), (t.currentTime = (t.duration / 10) * d)) break case 'Space': case 'k': f || V(t.togglePlay()) break case 'ArrowUp': t.increaseVolume(0.1) break case 'ArrowDown': t.decreaseVolume(0.1) break case 'm': f || (t.muted = !t.muted) break case 'ArrowRight': t.forward() break case 'ArrowLeft': t.rewind() break case 'f': t.fullscreen.toggle() break case 'c': f || t.toggleCaptions() break case 'l': t.loop = !t.loop } n === 'Escape' && !t.fullscreen.usingNative && t.fullscreen.active && t.fullscreen.toggle(), (this.lastKey = n) } else this.lastKey = null var d } } toggleMenu(i) { h.toggleMenu.call(this.player, i) } } function Ii(e, i) { return e((i = { exports: {} }), i.exports), i.exports } var Li = Ii(function (e, i) { e.exports = (function () { var t = function () {}, s = {}, n = {}, a = {} function r(d, v) { d = d.push ? d : [d] var T, k, N, w = [], M = d.length, g = M for ( T = function (S, L) { L.length && w.push(S), --g || v(w) }; M--; ) (k = d[M]), (N = n[k]) ? T(k, N) : (a[k] = a[k] || []).push(T) } function o(d, v) { if (d) { var T = a[d] if (((n[d] = v), T)) for (; T.length; ) T[0](d, v), T.splice(0, 1) } } function c(d, v) { d.call && (d = { success: d }), v.length ? (d.error || t)(v) : (d.success || t)(d) } function u(d, v, T, k) { var N, w, M = document, g = T.async, S = (T.numRetries || 0) + 1, L = T.before || t, D = d.replace(/[\?|#].*$/, ''), W = d.replace(/^(css|img)!/, '') ;(k = k || 0), /(^css!|\.css$)/.test(D) ? (((w = M.createElement('link')).rel = 'stylesheet'), (w.href = W), (N = 'hideFocus' in w) && w.relList && ((N = 0), (w.rel = 'preload'), (w.as = 'style'))) : /(^img!|\.(png|gif|jpg|svg|webp)$)/.test(D) ? ((w = M.createElement('img')).src = W) : (((w = M.createElement('script')).src = d), (w.async = g === void 0 || g)), (w.onload = w.onerror = w.onbeforeload = function (X) { var ue = X.type[0] if (N) try { w.sheet.cssText.length || (ue = 'e') } catch (Ct) { Ct.code != 18 && (ue = 'e') } if (ue == 'e') { if ((k += 1) < S) return u(d, v, T, k) } else if (w.rel == 'preload' && w.as == 'style') return (w.rel = 'stylesheet') v(d, ue, X.defaultPrevented) }), L(d, w) !== !1 && M.head.appendChild(w) } function p(d, v, T) { var k, N, w = (d = d.push ? d : [d]).length, M = w, g = [] for ( k = function (S, L, D) { if ((L == 'e' && g.push(S), L == 'b')) { if (!D) return g.push(S) } --w || v(g) }, N = 0; N < M; N++ ) u(d[N], k, T) } function f(d, v, T) { var k, N if ((v && v.trim && (k = v), (N = (k ? T : v) || {}), k)) { if (k in s) throw 'LoadJS' s[k] = !0 } function w(M, g) { p( d, function (S) { c(N, S), M && c({ success: M, error: g }, S), o(k, S) }, N ) } if (N.returnPromise) return new Promise(w) w() } return ( (f.ready = function (d, v) { return ( r(d, function (T) { c(v, T) }), f ) }), (f.done = function (d) { o(d, []) }), (f.reset = function () { ;(s = {}), (n = {}), (a = {}) }), (f.isDefined = function (d) { return d in s }), f ) })() }) function $e(e) { return new Promise((i, t) => { Li(e, { success: i, error: t }) }) } function Oi(e) { return l.empty(e) ? null : l.number(Number(e)) ? e : e.match(/^.*(vimeo.com\/|video\/)(\d+).*/) ? RegExp.$2 : e } function $i(e) { const i = e.match(/^.*(vimeo.com\/|video\/)(\d+)(\?.*&*h=|\/)+([\d,a-f]+)/) return i && i.length === 5 ? i[4] : null } function re(e) { e && !this.embed.hasPlayed && (this.embed.hasPlayed = !0), this.media.paused === e && ((this.media.paused = !e), b.call(this, this.media, e ? 'play' : 'pause')) } const _e = { setup() { const e = this A(e.elements.wrapper, e.config.classNames.embed, !0), (e.options.speed = e.config.speed.options), te.call(e), l.object(window.Vimeo) ? _e.ready.call(e) : $e(e.config.urls.vimeo.sdk) .then(() => { _e.ready.call(e) }) .catch(i => { e.debug.warn('Vimeo SDK (player.js) failed to load', i) }) }, ready() { const e = this, i = e.config.vimeo, M = i, { premium: t, referrerPolicy: s } = M, n = Fe(M, ['premium', 'referrerPolicy']) let a = e.media.getAttribute('src'), r = '' l.empty(a) ? ((a = e.media.getAttribute(e.config.attributes.embed.id)), (r = e.media.getAttribute(e.config.attributes.embed.hash))) : (r = $i(a)) const o = r ? { h: r } : {} t && Object.assign(n, { controls: !1, sidedock: !1 }) const c = vt( q( q( { loop: e.config.loop.active, autoplay: e.autoplay, muted: e.muted, gesture: 'media', playsinline: !this.config.fullscreen.iosNative }, o ), n ) ), u = Oi(a), p = y('iframe'), f = xe(e.config.urls.vimeo.iframe, u, c) if ( (p.setAttribute('src', f), p.setAttribute('allowfullscreen', ''), p.setAttribute( 'allow', [ 'autoplay', 'fullscreen', 'picture-in-picture', 'encrypted-media', 'accelerometer', 'gyroscope' ].join('; ') ), l.empty(s) || p.setAttribute('referrerPolicy', s), t || !i.customControls) ) p.setAttribute('data-poster', e.poster), (e.media = pe(p, e.media)) else { const g = y('div', { class: e.config.classNames.embedContainer, 'data-poster': e.poster }) g.appendChild(p), (e.media = pe(g, e.media)) } i.customControls || le(xe(e.config.urls.vimeo.api, f)).then(g => { !l.empty(g) && g.thumbnail_url && P.setPoster.call(e, g.thumbnail_url).catch(() => {}) }), (e.embed = new window.Vimeo.Player(p, { autopause: e.config.autopause, muted: e.muted })), (e.media.paused = !0), (e.media.currentTime = 0), e.supported.ui && e.embed.disableTextTrack(), (e.media.play = () => (re.call(e, !0), e.embed.play())), (e.media.pause = () => (re.call(e, !1), e.embed.pause())), (e.media.stop = () => { e.pause(), (e.currentTime = 0) }) let { currentTime: d } = e.media Object.defineProperty(e.media, 'currentTime', { get: () => d, set(g) { const { embed: S, media: L, paused: D, volume: W } = e, X = D && !S.hasPlayed ;(L.seeking = !0), b.call(e, L, 'seeking'), Promise.resolve(X && S.setVolume(0)) .then(() => S.setCurrentTime(g)) .then(() => X && S.pause()) .then(() => X && S.setVolume(W)) .catch(() => {}) } }) let v = e.config.speed.selected Object.defineProperty(e.media, 'playbackRate', { get: () => v, set(g) { e.embed .setPlaybackRate(g) .then(() => { ;(v = g), b.call(e, e.media, 'ratechange') }) .catch(() => { e.options.speed = [1] }) } }) let { volume: T } = e.config Object.defineProperty(e.media, 'volume', { get: () => T, set(g) { e.embed.setVolume(g).then(() => { ;(T = g), b.call(e, e.media, 'volumechange') }) } }) let { muted: k } = e.config Object.defineProperty(e.media, 'muted', { get: () => k, set(g) { const S = !!l.boolean(g) && g e.embed.setVolume(S ? 0 : e.config.volume).then(() => { ;(k = S), b.call(e, e.media, 'volumechange') }) } }) let N, { loop: w } = e.config Object.defineProperty(e.media, 'loop', { get: () => w, set(g) { const S = l.boolean(g) ? g : e.config.loop.active e.embed.setLoop(S).then(() => { w = S }) } }), e.embed .getVideoUrl() .then(g => { ;(N = g), h.setDownloadUrl.call(e) }) .catch(g => { this.debug.warn(g) }), Object.defineProperty(e.media, 'currentSrc', { get: () => N }), Object.defineProperty(e.media, 'ended', { get: () => e.currentTime === e.duration }), Promise.all([e.embed.getVideoWidth(), e.embed.getVideoHeight()]).then( g => { const [S, L] = g ;(e.embed.ratio = mt(S, L)), te.call(this) } ), e.embed.setAutopause(e.config.autopause).then(g => { e.config.autopause = g }), e.embed.getVideoTitle().then(g => { ;(e.config.title = g), P.setTitle.call(this) }), e.embed.getCurrentTime().then(g => { ;(d = g), b.call(e, e.media, 'timeupdate') }), e.embed.getDuration().then(g => { ;(e.media.duration = g), b.call(e, e.media, 'durationchange') }), e.embed.getTextTracks().then(g => { ;(e.media.textTracks = g), E.setup.call(e) }), e.embed.on('cuechange', ({ cues: g = [] }) => { const S = g.map(L => Si(L.text)) E.updateCues.call(e, S) }), e.embed.on('loaded', () => { e.embed.getPaused().then(g => { re.call(e, !g), g || b.call(e, e.media, 'playing') }), l.element(e.embed.element) && e.supported.ui && e.embed.element.setAttribute('tabindex', -1) }), e.embed.on('bufferstart', () => { b.call(e, e.media, 'waiting') }), e.embed.on('bufferend', () => { b.call(e, e.media, 'playing') }), e.embed.on('play', () => { re.call(e, !0), b.call(e, e.media, 'playing') }), e.embed.on('pause', () => { re.call(e, !1) }), e.embed.on('timeupdate', g => { ;(e.media.seeking = !1), (d = g.seconds), b.call(e, e.media, 'timeupdate') }), e.embed.on('progress', g => { ;(e.media.buffered = g.percent), b.call(e, e.media, 'progress'), parseInt(g.percent, 10) === 1 && b.call(e, e.media, 'canplaythrough'), e.embed.getDuration().then(S => { S !== e.media.duration && ((e.media.duration = S), b.call(e, e.media, 'durationchange')) }) }), e.embed.on('seeked', () => { ;(e.media.seeking = !1), b.call(e, e.media, 'seeked') }), e.embed.on('ended', () => { ;(e.media.paused = !0), b.call(e, e.media, 'ended') }), e.embed.on('error', g => { ;(e.media.error = g), b.call(e, e.media, 'error') }), i.customControls && setTimeout(() => P.build.call(e), 0) } } function _i(e) { return l.empty(e) ? null : e.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/) ? RegExp.$2 : e } function oe(e) { e && !this.embed.hasPlayed && (this.embed.hasPlayed = !0), this.media.paused === e && ((this.media.paused = !e), b.call(this, this.media, e ? 'play' : 'pause')) } function Ri(e) { return e.noCookie ? 'https://www.youtube-nocookie.com' : window.location.protocol === 'http:' ? 'http://www.youtube.com' : void 0 } const we = { setup() { if ( (A(this.elements.wrapper, this.config.classNames.embed, !0), l.object(window.YT) && l.function(window.YT.Player)) ) we.ready.call(this) else { const e = window.onYouTubeIframeAPIReady ;(window.onYouTubeIframeAPIReady = () => { l.function(e) && e(), we.ready.call(this) }), $e(this.config.urls.youtube.sdk).catch(i => { this.debug.warn('YouTube API failed to load', i) }) } }, getTitle(e) { le(xe(this.config.urls.youtube.api, e)) .then(i => { if (l.object(i)) { const { title: t, height: s, width: n } = i ;(this.config.title = t), P.setTitle.call(this), (this.embed.ratio = mt(n, s)) } te.call(this) }) .catch(() => { te.call(this) }) }, ready() { const e = this, i = e.config.youtube, t = e.media && e.media.getAttribute('id') if (!l.empty(t) && t.startsWith('youtube-')) return let s = e.media.getAttribute('src') l.empty(s) && (s = e.media.getAttribute(this.config.attributes.embed.id)) const n = _i(s), a = y('div', { id: Ti(e.provider), 'data-poster': i.customControls ? e.poster : void 0 }) if (((e.media = pe(a, e.media)), i.customControls)) { const r = o => `https://i.ytimg.com/vi/${n}/${o}default.jpg` ve(r('maxres'), 121) .catch(() => ve(r('sd'), 121)) .catch(() => ve(r('hq'))) .then(o => P.setPoster.call(e, o.src)) .then(o => { o.includes('maxres') || (e.elements.poster.style.backgroundSize = 'cover') }) .catch(() => {}) } e.embed = new window.YT.Player(e.media, { videoId: n, host: Ri(i), playerVars: I( {}, { autoplay: e.config.autoplay ? 1 : 0, hl: e.config.hl, controls: e.supported.ui && i.customControls ? 0 : 1, disablekb: 1, playsinline: e.config.fullscreen.iosNative ? 0 : 1, cc_load_policy: e.captions.active ? 1 : 0, cc_lang_pref: e.config.captions.language, widget_referrer: window ? window.location.href : null }, i ), events: { onError(r) { if (!e.media.error) { const o = r.data, c = { 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.', 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.', 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.', 101: 'The owner of the requested video does not allow it to be played in embedded players.', 150: 'The owner of the requested video does not allow it to be played in embedded players.' }[o] || 'An unknown error occured' ;(e.media.error = { code: o, message: c }), b.call(e, e.media, 'error') } }, onPlaybackRateChange(r) { const o = r.target ;(e.media.playbackRate = o.getPlaybackRate()), b.call(e, e.media, 'ratechange') }, onReady(r) { if (l.function(e.media.play)) return const o = r.target we.getTitle.call(e, n), (e.media.play = () => { oe.call(e, !0), o.playVideo() }), (e.media.pause = () => { oe.call(e, !1), o.pauseVideo() }), (e.media.stop = () => { o.stopVideo() }), (e.media.duration = o.getDuration()), (e.media.paused = !0), (e.media.currentTime = 0), Object.defineProperty(e.media, 'currentTime', { get: () => Number(o.getCurrentTime()), set(f) { e.paused && !e.embed.hasPlayed && e.embed.mute(), (e.media.seeking = !0), b.call(e, e.media, 'seeking'), o.seekTo(f) } }), Object.defineProperty(e.media, 'playbackRate', { get: () => o.getPlaybackRate(), set(f) { o.setPlaybackRate(f) } }) let { volume: c } = e.config Object.defineProperty(e.media, 'volume', { get: () => c, set(f) { ;(c = f), o.setVolume(100 * c), b.call(e, e.media, 'volumechange') } }) let { muted: u } = e.config Object.defineProperty(e.media, 'muted', { get: () => u, set(f) { const d = l.boolean(f) ? f : u ;(u = d), o[d ? 'mute' : 'unMute'](), o.setVolume(100 * c), b.call(e, e.media, 'volumechange') } }), Object.defineProperty(e.media, 'currentSrc', { get: () => o.getVideoUrl() }), Object.defineProperty(e.media, 'ended', { get: () => e.currentTime === e.duration }) const p = o.getAvailablePlaybackRates() ;(e.options.speed = p.filter(f => e.config.speed.options.includes(f) )), e.supported.ui && i.customControls && e.media.setAttribute('tabindex', -1), b.call(e, e.media, 'timeupdate'), b.call(e, e.media, 'durationchange'), clearInterval(e.timers.buffering), (e.timers.buffering = setInterval(() => { ;(e.media.buffered = o.getVideoLoadedFraction()), (e.media.lastBuffered === null || e.media.lastBuffered < e.media.buffered) && b.call(e, e.media, 'progress'), (e.media.lastBuffered = e.media.buffered), e.media.buffered === 1 && (clearInterval(e.timers.buffering), b.call(e, e.media, 'canplaythrough')) }, 200)), i.customControls && setTimeout(() => P.build.call(e), 50) }, onStateChange(r) { const o = r.target switch ( (clearInterval(e.timers.playing), e.media.seeking && [1, 2].includes(r.data) && ((e.media.seeking = !1), b.call(e, e.media, 'seeked')), r.data) ) { case -1: b.call(e, e.media, 'timeupdate'), (e.media.buffered = o.getVideoLoadedFraction()), b.call(e, e.media, 'progress') break case 0: oe.call(e, !1), e.media.loop ? (o.stopVideo(), o.playVideo()) : b.call(e, e.media, 'ended') break case 1: i.customControls && !e.config.autoplay && e.media.paused && !e.embed.hasPlayed ? e.media.pause() : (oe.call(e, !0), b.call(e, e.media, 'playing'), (e.timers.playing = setInterval(() => { b.call(e, e.media, 'timeupdate') }, 50)), e.media.duration !== o.getDuration() && ((e.media.duration = o.getDuration()), b.call(e, e.media, 'durationchange'))) break case 2: e.muted || e.embed.unMute(), oe.call(e, !1) break case 3: b.call(e, e.media, 'waiting') } b.call(e, e.elements.container, 'statechange', !1, { code: r.data }) } } }) } }, Tt = { setup() { this.media ? (A( this.elements.container, this.config.classNames.type.replace('{0}', this.type), !0 ), A( this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), !0 ), this.isEmbed && A( this.elements.container, this.config.classNames.type.replace('{0}', 'video'), !0 ), this.isVideo && ((this.elements.wrapper = y('div', { class: this.config.classNames.video })), lt(this.media, this.elements.wrapper), (this.elements.poster = y('div', { class: this.config.classNames.poster })), this.elements.wrapper.appendChild(this.elements.poster)), this.isHTML5 ? K.setup.call(this) : this.isYouTube ? we.setup.call(this) : this.isVimeo && _e.setup.call(this)) : this.debug.warn('No media element found!') } } class ji { constructor(i) { m(this, 'load', () => { this.enabled && (l.object(window.google) && l.object(window.google.ima) ? this.ready() : $e(this.player.config.urls.googleIMA.sdk) .then(() => { this.ready() }) .catch(() => { this.trigger( 'error', new Error('Google IMA SDK failed to load') ) })) }), m(this, 'ready', () => { var t this.enabled || ((t = this).manager && t.manager.destroy(), t.elements.displayContainer && t.elements.displayContainer.destroy(), t.elements.container.remove()), this.startSafetyTimer(12e3, 'ready()'), this.managerPromise.then(() => { this.clearSafetyTimer('onAdsManagerLoaded()') }), this.listeners(), this.setupIMA() }), m(this, 'setupIMA', () => { ;(this.elements.container = y('div', { class: this.player.config.classNames.ads })), this.player.elements.container.appendChild(this.elements.container), google.ima.settings.setVpaidMode( google.ima.ImaSdkSettings.VpaidMode.ENABLED ), google.ima.settings.setLocale(this.player.config.ads.language), google.ima.settings.setDisableCustomPlaybackForIOS10Plus( this.player.config.playsinline ), (this.elements.displayContainer = new google.ima.AdDisplayContainer( this.elements.container, this.player.media )), (this.loader = new google.ima.AdsLoader( this.elements.displayContainer )), this.loader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, t => this.onAdsManagerLoaded(t), !1 ), this.loader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, t => this.onAdError(t), !1 ), this.requestAds() }), m(this, 'requestAds', () => { const { container: t } = this.player.elements try { const s = new google.ima.AdsRequest() ;(s.adTagUrl = this.tagUrl), (s.linearAdSlotWidth = t.offsetWidth), (s.linearAdSlotHeight = t.offsetHeight), (s.nonLinearAdSlotWidth = t.offsetWidth), (s.nonLinearAdSlotHeight = t.offsetHeight), (s.forceNonLinearFullSlot = !1), s.setAdWillPlayMuted(!this.player.muted), this.loader.requestAds(s) } catch (s) { this.onAdError(s) } }), m(this, 'pollCountdown', (t = !1) => { if (!t) return ( clearInterval(this.countdownTimer), void this.elements.container.removeAttribute('data-badge-text') ) this.countdownTimer = setInterval(() => { const s = be(Math.max(this.manager.getRemainingTime(), 0)), n = `${$.get('advertisement', this.player.config)} - ${s}` this.elements.container.setAttribute('data-badge-text', n) }, 100) }), m(this, 'onAdsManagerLoaded', t => { if (!this.enabled) return const s = new google.ima.AdsRenderingSettings() ;(s.restoreCustomPlaybackStateOnAdBreakComplete = !0), (s.enablePreloading = !0), (this.manager = t.getAdsManager(this.player, s)), (this.cuePoints = this.manager.getCuePoints()), this.manager.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, n => this.onAdError(n) ), Object.keys(google.ima.AdEvent.Type).forEach(n => { this.manager.addEventListener(google.ima.AdEvent.Type[n], a => this.onAdEvent(a) ) }), this.trigger('loaded') }), m(this, 'addCuePoints', () => { l.empty(this.cuePoints) || this.cuePoints.forEach(t => { if (t !== 0 && t !== -1 && t < this.player.duration) { const s = this.player.elements.progress if (l.element(s)) { const n = (100 / this.player.duration) * t, a = y('span', { class: this.player.config.classNames.cues }) ;(a.style.left = `${n.toString()}%`), s.appendChild(a) } } }) }), m(this, 'onAdEvent', t => { const { container: s } = this.player.elements, n = t.getAd(), a = t.getAdData() switch ( ((r => { b.call( this.player, this.player.media, `ads${r.replace(/_/g, '').toLowerCase()}` ) })(t.type), t.type) ) { case google.ima.AdEvent.Type.LOADED: this.trigger('loaded'), this.pollCountdown(!0), n.isLinear() || ((n.width = s.offsetWidth), (n.height = s.offsetHeight)) break case google.ima.AdEvent.Type.STARTED: this.manager.setVolume(this.player.volume) break case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: this.player.ended ? this.loadAds() : this.loader.contentComplete() break case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: this.pauseContent() break case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED: this.pollCountdown(), this.resumeContent() break case google.ima.AdEvent.Type.LOG: a.adError && this.player.debug.warn( `Non-fatal ad error: ${a.adError.getMessage()}` ) } }), m(this, 'onAdError', t => { this.cancel(), this.player.debug.warn('Ads error', t) }), m(this, 'listeners', () => { const { container: t } = this.player.elements let s this.player.on('canplay', () => { this.addCuePoints() }), this.player.on('ended', () => { this.loader.contentComplete() }), this.player.on('timeupdate', () => { s = this.player.currentTime }), this.player.on('seeked', () => { const n = this.player.currentTime l.empty(this.cuePoints) || this.cuePoints.forEach((a, r) => { s < a && a < n && (this.manager.discardAdBreak(), this.cuePoints.splice(r, 1)) }) }), window.addEventListener('resize', () => { this.manager && this.manager.resize( t.offsetWidth, t.offsetHeight, google.ima.ViewMode.NORMAL ) }) }), m(this, 'play', () => { const { container: t } = this.player.elements this.managerPromise || this.resumeContent(), this.managerPromise .then(() => { this.manager.setVolume(this.player.volume), this.elements.displayContainer.initialize() try { this.initialized || (this.manager.init( t.offsetWidth, t.offsetHeight, google.ima.ViewMode.NORMAL ), this.manager.start()), (this.initialized = !0) } catch (s) { this.onAdError(s) } }) .catch(() => {}) }), m(this, 'resumeContent', () => { ;(this.elements.container.style.zIndex = ''), (this.playing = !1), V(this.player.media.play()) }), m(this, 'pauseContent', () => { ;(this.elements.container.style.zIndex = 3), (this.playing = !0), this.player.media.pause() }), m(this, 'cancel', () => { this.initialized && this.resumeContent(), this.trigger('error'), this.loadAds() }), m(this, 'loadAds', () => { this.managerPromise .then(() => { this.manager && this.manager.destroy(), (this.managerPromise = new Promise(t => { this.on('loaded', t), this.player.debug.log(this.manager) })), (this.initialized = !1), this.requestAds() }) .catch(() => {}) }), m(this, 'trigger', (t, ...s) => { const n = this.events[t] l.array(n) && n.forEach(a => { l.function(a) && a.apply(this, s) }) }), m( this, 'on', (t, s) => ( l.array(this.events[t]) || (this.events[t] = []), this.events[t].push(s), this ) ), m(this, 'startSafetyTimer', (t, s) => { this.player.debug.log(`Safety timer invoked from: ${s}`), (this.safetyTimer = setTimeout(() => { this.cancel(), this.clearSafetyTimer('startSafetyTimer()') }, t)) }), m(this, 'clearSafetyTimer', t => { l.nullOrUndefined(this.safetyTimer) || (this.player.debug.log(`Safety timer cleared from: ${t}`), clearTimeout(this.safetyTimer), (this.safetyTimer = null)) }), (this.player = i), (this.config = i.config.ads), (this.playing = !1), (this.initialized = !1), (this.elements = { container: null, displayContainer: null }), (this.manager = null), (this.loader = null), (this.cuePoints = null), (this.events = {}), (this.safetyTimer = null), (this.countdownTimer = null), (this.managerPromise = new Promise((t, s) => { this.on('loaded', t), this.on('error', s) })), this.load() } get enabled() { const { config: i } = this return ( this.player.isHTML5 && this.player.isVideo && i.enabled && (!l.empty(i.publisherId) || l.url(i.tagUrl)) ) } get tagUrl() { const { config: i } = this return l.url(i.tagUrl) ? i.tagUrl : `https://go.aniview.com/api/adserver6/vast/?${vt({ AV_PUBLISHERID: '58c25bb0073ef448b1087ad6', AV_CHANNELID: '5a0458dc28a06145e4519d21', AV_URL: window.location.hostname, cb: Date.now(), AV_WIDTH: 640, AV_HEIGHT: 480, AV_CDIM2: i.publisherId })}` } } function kt(e = 0, i = 0, t = 255) { return Math.min(Math.max(e, i), t) } const Di = e => { const i = [] return ( e.split(/\r\n\r\n|\n\n|\r\r/).forEach(t => { const s = {} t.split(/\r\n|\n|\r/).forEach(n => { if (l.number(s.startTime)) { if (!l.empty(n.trim()) && l.empty(s.text)) { const a = n.trim().split('#xywh=') ;([s.text] = a), a[1] && ([s.x, s.y, s.w, s.h] = a[1].split(',')) } } else { const a = n.match( /([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})/ ) a && ((s.startTime = 60 * Number(a[1] || 0) * 60 + 60 * Number(a[2]) + Number(a[3]) + Number(`0.${a[4]}`)), (s.endTime = 60 * Number(a[6] || 0) * 60 + 60 * Number(a[7]) + Number(a[8]) + Number(`0.${a[9]}`))) } }), s.text && i.push(s) }), i ) }, At = (e, i) => { const t = {} return ( e > i.width / i.height ? ((t.width = i.width), (t.height = (1 / e) * i.width)) : ((t.height = i.height), (t.width = e * i.height)), t ) } class Re { constructor(i) { m(this, 'load', () => { this.player.elements.display.seekTooltip && (this.player.elements.display.seekTooltip.hidden = this.enabled), this.enabled && this.getThumbnails().then(() => { this.enabled && (this.render(), this.determineContainerAutoSizing(), (this.loaded = !0)) }) }), m( this, 'getThumbnails', () => new Promise(t => { const { src: s } = this.player.config.previewThumbnails if (l.empty(s)) throw new Error('Missing previewThumbnails.src config attribute') const n = () => { this.thumbnails.sort((a, r) => a.height - r.height), this.player.debug.log('Preview thumbnails', this.thumbnails), t() } if (l.function(s)) s(a => { ;(this.thumbnails = a), n() }) else { const a = (l.string(s) ? [s] : s).map(r => this.getThumbnail(r)) Promise.all(a).then(n) } }) ), m( this, 'getThumbnail', t => new Promise(s => { le(t).then(n => { const a = { frames: Di(n), height: null, urlPrefix: '' } a.frames[0].text.startsWith('/') || a.frames[0].text.startsWith('http://') || a.frames[0].text.startsWith('https://') || (a.urlPrefix = t.substring(0, t.lastIndexOf('/') + 1)) const r = new Image() ;(r.onload = () => { ;(a.height = r.naturalHeight), (a.width = r.naturalWidth), this.thumbnails.push(a), s() }), (r.src = a.urlPrefix + a.frames[0].text) }) }) ), m(this, 'startMove', t => { if ( this.loaded && l.event(t) && ['touchmove', 'mousemove'].includes(t.type) && this.player.media.duration ) { if (t.type === 'touchmove') this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100) else { var s, n const a = this.player.elements.progress.getBoundingClientRect(), r = (100 / a.width) * (t.pageX - a.left) ;(this.seekTime = this.player.media.duration * (r / 100)), this.seekTime < 0 && (this.seekTime = 0), this.seekTime > this.player.media.duration - 1 && (this.seekTime = this.player.media.duration - 1), (this.mousePosX = t.pageX), (this.elements.thumb.time.innerText = be(this.seekTime)) const o = (s = this.player.config.markers) === null || s === void 0 || (n = s.points) === null || n === void 0 ? void 0 : n.find(({ time: c }) => c === Math.round(this.seekTime)) o && this.elements.thumb.time.insertAdjacentHTML( 'afterbegin', `${o.label}
` ) } this.showImageAtCurrentTime() } }), m(this, 'endMove', () => { this.toggleThumbContainer(!1, !0) }), m(this, 'startScrubbing', t => { ;(l.nullOrUndefined(t.button) || t.button === !1 || t.button === 0) && ((this.mouseDown = !0), this.player.media.duration && (this.toggleScrubbingContainer(!0), this.toggleThumbContainer(!1, !0), this.showImageAtCurrentTime())) }), m(this, 'endScrubbing', () => { ;(this.mouseDown = !1), Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime) ? this.toggleScrubbingContainer(!1) : Pe.call(this.player, this.player.media, 'timeupdate', () => { this.mouseDown || this.toggleScrubbingContainer(!1) }) }), m(this, 'listeners', () => { this.player.on('play', () => { this.toggleThumbContainer(!1, !0) }), this.player.on('seeked', () => { this.toggleThumbContainer(!1) }), this.player.on('timeupdate', () => { this.lastTime = this.player.media.currentTime }) }), m(this, 'render', () => { ;(this.elements.thumb.container = y('div', { class: this.player.config.classNames.previewThumbnails.thumbContainer })), (this.elements.thumb.imageContainer = y('div', { class: this.player.config.classNames.previewThumbnails.imageContainer })), this.elements.thumb.container.appendChild( this.elements.thumb.imageContainer ) const t = y('div', { class: this.player.config.classNames.previewThumbnails.timeContainer }) ;(this.elements.thumb.time = y('span', {}, '00:00')), t.appendChild(this.elements.thumb.time), this.elements.thumb.imageContainer.appendChild(t), l.element(this.player.elements.progress) && this.player.elements.progress.appendChild( this.elements.thumb.container ), (this.elements.scrubbing.container = y('div', { class: this.player.config.classNames.previewThumbnails.scrubbingContainer })), this.player.elements.wrapper.appendChild( this.elements.scrubbing.container ) }), m(this, 'destroy', () => { this.elements.thumb.container && this.elements.thumb.container.remove(), this.elements.scrubbing.container && this.elements.scrubbing.container.remove() }), m(this, 'showImageAtCurrentTime', () => { this.mouseDown ? this.setScrubbingContainerSize() : this.setThumbContainerSizeAndPos() const t = this.thumbnails[0].frames.findIndex( a => this.seekTime >= a.startTime && this.seekTime <= a.endTime ), s = t >= 0 let n = 0 this.mouseDown || this.toggleThumbContainer(s), s && (this.thumbnails.forEach((a, r) => { this.loadedImages.includes(a.frames[t].text) && (n = r) }), t !== this.showingThumb && ((this.showingThumb = t), this.loadImage(n))) }), m(this, 'loadImage', (t = 0) => { const s = this.showingThumb, n = this.thumbnails[t], { urlPrefix: a } = n, r = n.frames[s], o = n.frames[s].text, c = a + o if ( this.currentImageElement && this.currentImageElement.dataset.filename === o ) this.showImage(this.currentImageElement, r, t, s, o, !1), (this.currentImageElement.dataset.index = s), this.removeOldImages(this.currentImageElement) else { this.loadingImage && this.usingSprites && (this.loadingImage.onload = null) const u = new Image() ;(u.src = c), (u.dataset.index = s), (u.dataset.filename = o), (this.showingThumbFilename = o), this.player.debug.log(`Loading image: ${c}`), (u.onload = () => this.showImage(u, r, t, s, o, !0)), (this.loadingImage = u), this.removeOldImages(u) } }), m(this, 'showImage', (t, s, n, a, r, o = !0) => { this.player.debug.log( `Showing thumb: ${r}. num: ${a}. qual: ${n}. newimg: ${o}` ), this.setImageSizeAndOffset(t, s), o && (this.currentImageContainer.appendChild(t), (this.currentImageElement = t), this.loadedImages.includes(r) || this.loadedImages.push(r)), this.preloadNearby(a, !0) .then(this.preloadNearby(a, !1)) .then(this.getHigherQuality(n, t, s, r)) }), m(this, 'removeOldImages', t => { Array.from(this.currentImageContainer.children).forEach(s => { if (s.tagName.toLowerCase() !== 'img') return const n = this.usingSprites ? 500 : 1e3 if (s.dataset.index !== t.dataset.index && !s.dataset.deleting) { s.dataset.deleting = !0 const { currentImageContainer: a } = this setTimeout(() => { a.removeChild(s), this.player.debug.log(`Removing thumb: ${s.dataset.filename}`) }, n) } }) }), m( this, 'preloadNearby', (t, s = !0) => new Promise(n => { setTimeout(() => { const a = this.thumbnails[0].frames[t].text if (this.showingThumbFilename === a) { let r r = s ? this.thumbnails[0].frames.slice(t) : this.thumbnails[0].frames.slice(0, t).reverse() let o = !1 r.forEach(c => { const u = c.text if (u !== a && !this.loadedImages.includes(u)) { ;(o = !0), this.player.debug.log(`Preloading thumb filename: ${u}`) const { urlPrefix: p } = this.thumbnails[0], f = p + u, d = new Image() ;(d.src = f), (d.onload = () => { this.player.debug.log(`Preloaded thumb filename: ${u}`), this.loadedImages.includes(u) || this.loadedImages.push(u), n() }) } }), o || n() } }, 300) }) ), m(this, 'getHigherQuality', (t, s, n, a) => { if (t < this.thumbnails.length - 1) { let r = s.naturalHeight this.usingSprites && (r = n.h), r < this.thumbContainerHeight && setTimeout(() => { this.showingThumbFilename === a && (this.player.debug.log( `Showing higher quality thumb for: ${a}` ), this.loadImage(t + 1)) }, 300) } }), m(this, 'toggleThumbContainer', (t = !1, s = !1) => { const n = this.player.config.classNames.previewThumbnails.thumbContainerShown this.elements.thumb.container.classList.toggle(n, t), !t && s && ((this.showingThumb = null), (this.showingThumbFilename = null)) }), m(this, 'toggleScrubbingContainer', (t = !1) => { const s = this.player.config.classNames.previewThumbnails .scrubbingContainerShown this.elements.scrubbing.container.classList.toggle(s, t), t || ((this.showingThumb = null), (this.showingThumbFilename = null)) }), m(this, 'determineContainerAutoSizing', () => { ;(this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) && (this.sizeSpecifiedInCSS = !0) }), m(this, 'setThumbContainerSizeAndPos', () => { const { imageContainer: t } = this.elements.thumb if (this.sizeSpecifiedInCSS) { if (t.clientHeight > 20 && t.clientWidth < 20) { const s = Math.floor(t.clientHeight * this.thumbAspectRatio) t.style.width = `${s}px` } else if (t.clientHeight < 20 && t.clientWidth > 20) { const s = Math.floor(t.clientWidth / this.thumbAspectRatio) t.style.height = `${s}px` } } else { const s = Math.floor( this.thumbContainerHeight * this.thumbAspectRatio ) ;(t.style.height = `${this.thumbContainerHeight}px`), (t.style.width = `${s}px`) } this.setThumbContainerPos() }), m(this, 'setThumbContainerPos', () => { const t = this.player.elements.progress.getBoundingClientRect(), s = this.player.elements.container.getBoundingClientRect(), { container: n } = this.elements.thumb, a = s.left - t.left + 10, r = s.right - t.left - n.clientWidth - 10, o = this.mousePosX - t.left - n.clientWidth / 2, c = kt(o, a, r) ;(n.style.left = `${c}px`), n.style.setProperty('--preview-arrow-offset', o - c + 'px') }), m(this, 'setScrubbingContainerSize', () => { const { width: t, height: s } = At(this.thumbAspectRatio, { width: this.player.media.clientWidth, height: this.player.media.clientHeight }) ;(this.elements.scrubbing.container.style.width = `${t}px`), (this.elements.scrubbing.container.style.height = `${s}px`) }), m(this, 'setImageSizeAndOffset', (t, s) => { if (!this.usingSprites) return const n = this.thumbContainerHeight / s.h ;(t.style.height = t.naturalHeight * n + 'px'), (t.style.width = t.naturalWidth * n + 'px'), (t.style.left = `-${s.x * n}px`), (t.style.top = `-${s.y * n}px`) }), (this.player = i), (this.thumbnails = []), (this.loaded = !1), (this.lastMouseMoveTime = Date.now()), (this.mouseDown = !1), (this.loadedImages = []), (this.elements = { thumb: {}, scrubbing: {} }), this.load() } get enabled() { return ( this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled ) } get currentImageContainer() { return this.mouseDown ? this.elements.scrubbing.container : this.elements.thumb.imageContainer } get usingSprites() { return Object.keys(this.thumbnails[0].frames[0]).includes('w') } get thumbAspectRatio() { return this.usingSprites ? this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h : this.thumbnails[0].width / this.thumbnails[0].height } get thumbContainerHeight() { if (this.mouseDown) { const { height: i } = At(this.thumbAspectRatio, { width: this.player.media.clientWidth, height: this.player.media.clientHeight }) return i } return this.sizeSpecifiedInCSS ? this.elements.thumb.imageContainer.clientHeight : Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4) } get currentImageElement() { return this.mouseDown ? this.currentScrubbingImageElement : this.currentThumbnailImageElement } set currentImageElement(i) { this.mouseDown ? (this.currentScrubbingImageElement = i) : (this.currentThumbnailImageElement = i) } } const je = { insertElements(e, i) { l.string(i) ? rt(e, this.media, { src: i }) : l.array(i) && i.forEach(t => { rt(e, this.media, t) }) }, change(e) { at(e, 'sources.length') ? (K.cancelRequests.call(this), this.destroy.call( this, () => { ;(this.options.quality = []), z(this.media), (this.media = null), l.element(this.elements.container) && this.elements.container.removeAttribute('class') const { sources: i, type: t } = e, [{ provider: s = Y.html5, src: n }] = i, a = s === 'html5' ? t : 'div', r = s === 'html5' ? {} : { src: n } Object.assign(this, { provider: s, type: t, supported: x.check(t, s, this.config.playsinline), media: y(a, r) }), this.elements.container.appendChild(this.media), l.boolean(e.autoplay) && (this.config.autoplay = e.autoplay), this.isHTML5 && (this.config.crossorigin && this.media.setAttribute('crossorigin', ''), this.config.autoplay && this.media.setAttribute('autoplay', ''), l.empty(e.poster) || (this.poster = e.poster), this.config.loop.active && this.media.setAttribute('loop', ''), this.config.muted && this.media.setAttribute('muted', ''), this.config.playsinline && this.media.setAttribute('playsinline', '')), P.addStyleHook.call(this), this.isHTML5 && je.insertElements.call(this, 'source', i), (this.config.title = e.title), Tt.setup.call(this), this.isHTML5 && Object.keys(e).includes('tracks') && je.insertElements.call(this, 'track', e.tracks), (this.isHTML5 || (this.isEmbed && !this.supported.ui)) && P.build.call(this), this.isHTML5 && this.media.load(), l.empty(e.previewThumbnails) || (Object.assign( this.config.previewThumbnails, e.previewThumbnails ), this.previewThumbnails && this.previewThumbnails.loaded && (this.previewThumbnails.destroy(), (this.previewThumbnails = null)), this.config.previewThumbnails.enabled && (this.previewThumbnails = new Re(this))), this.fullscreen.update() }, !0 )) : this.debug.warn('Invalid source format') } } class ce { constructor(i, t) { if ( (m(this, 'play', () => l.function(this.media.play) ? (this.ads && this.ads.enabled && this.ads.managerPromise .then(() => this.ads.play()) .catch(() => V(this.media.play())), this.media.play()) : null ), m(this, 'pause', () => this.playing && l.function(this.media.pause) ? this.media.pause() : null ), m(this, 'togglePlay', o => (l.boolean(o) ? o : !this.playing) ? this.play() : this.pause() ), m(this, 'stop', () => { this.isHTML5 ? (this.pause(), this.restart()) : l.function(this.media.stop) && this.media.stop() }), m(this, 'restart', () => { this.currentTime = 0 }), m(this, 'rewind', o => { this.currentTime -= l.number(o) ? o : this.config.seekTime }), m(this, 'forward', o => { this.currentTime += l.number(o) ? o : this.config.seekTime }), m(this, 'increaseVolume', o => { const c = this.media.muted ? 0 : this.volume this.volume = c + (l.number(o) ? o : 0) }), m(this, 'decreaseVolume', o => { this.increaseVolume(-o) }), m(this, 'airplay', () => { x.airplay && this.media.webkitShowPlaybackTargetPicker() }), m(this, 'toggleControls', o => { if (this.supported.ui && !this.isAudio) { const c = ge( this.elements.container, this.config.classNames.hideControls ), u = o === void 0 ? void 0 : !o, p = A( this.elements.container, this.config.classNames.hideControls, u ) if ( (p && l.array(this.config.controls) && this.config.controls.includes('settings') && !l.empty(this.config.settings) && h.toggleMenu.call(this, !1), p !== c) ) { const f = p ? 'controlshidden' : 'controlsshown' b.call(this, this.media, f) } return !p } return !1 }), m(this, 'on', (o, c) => { C.call(this, this.elements.container, o, c) }), m(this, 'once', (o, c) => { Pe.call(this, this.elements.container, o, c) }), m(this, 'off', (o, c) => { fe(this.elements.container, o, c) }), m(this, 'destroy', (o, c = !1) => { if (!this.ready) return const u = () => { ;(document.body.style.overflow = ''), (this.embed = null), c ? (Object.keys(this.elements).length && (z(this.elements.buttons.play), z(this.elements.captions), z(this.elements.controls), z(this.elements.wrapper), (this.elements.buttons.play = null), (this.elements.captions = null), (this.elements.controls = null), (this.elements.wrapper = null)), l.function(o) && o()) : (bi.call(this), K.cancelRequests.call(this), pe(this.elements.original, this.elements.container), b.call(this, this.elements.original, 'destroyed', !0), l.function(o) && o.call(this.elements.original), (this.ready = !1), setTimeout(() => { ;(this.elements = null), (this.media = null) }, 200)) } this.stop(), clearTimeout(this.timers.loading), clearTimeout(this.timers.controls), clearTimeout(this.timers.resized), this.isHTML5 ? (P.toggleNativeControls.call(this, !0), u()) : this.isYouTube ? (clearInterval(this.timers.buffering), clearInterval(this.timers.playing), this.embed !== null && l.function(this.embed.destroy) && this.embed.destroy(), u()) : this.isVimeo && (this.embed !== null && this.embed.unload().then(u), setTimeout(u, 200)) }), m(this, 'supports', o => x.mime.call(this, o)), (this.timers = {}), (this.ready = !1), (this.loading = !1), (this.failed = !1), (this.touch = x.touch), (this.media = i), l.string(this.media) && (this.media = document.querySelectorAll(this.media)), ((window.jQuery && this.media instanceof jQuery) || l.nodeList(this.media) || l.array(this.media)) && (this.media = this.media[0]), (this.config = I( {}, wt, ce.defaults, t || {}, (() => { try { return JSON.parse(this.media.getAttribute('data-plyr-config')) } catch { return {} } })() )), (this.elements = { container: null, fullscreen: null, captions: null, buttons: {}, display: {}, progress: {}, inputs: {}, settings: { popup: null, menu: null, panels: {}, buttons: {} } }), (this.captions = { active: null, currentTrack: -1, meta: new WeakMap() }), (this.fullscreen = { active: !1 }), (this.options = { speed: [], quality: [] }), (this.debug = new Mi(this.config.debug)), this.debug.log('Config', this.config), this.debug.log('Support', x), l.nullOrUndefined(this.media) || !l.element(this.media)) ) return void this.debug.error('Setup failed: no suitable element passed') if (this.media.plyr) return void this.debug.warn('Target already setup') if (!this.config.enabled) return void this.debug.error('Setup failed: disabled by config') if (!x.check().api) return void this.debug.error('Setup failed: no support') const s = this.media.cloneNode(!0) ;(s.autoplay = !1), (this.elements.original = s) const n = this.media.tagName.toLowerCase() let a = null, r = null switch (n) { case 'div': if (((a = this.media.querySelector('iframe')), l.element(a))) { if ( ((r = bt(a.getAttribute('src'))), (this.provider = Ni(r.toString())), (this.elements.container = this.media), (this.media = a), (this.elements.container.className = ''), r.search.length) ) { const o = ['1', 'true'] o.includes(r.searchParams.get('autoplay')) && (this.config.autoplay = !0), o.includes(r.searchParams.get('loop')) && (this.config.loop.active = !0), this.isYouTube ? ((this.config.playsinline = o.includes( r.searchParams.get('playsinline') )), (this.config.youtube.hl = r.searchParams.get('hl'))) : (this.config.playsinline = !0) } } else (this.provider = this.media.getAttribute( this.config.attributes.embed.provider )), this.media.removeAttribute(this.config.attributes.embed.provider) if (l.empty(this.provider) || !Object.values(Y).includes(this.provider)) return void this.debug.error('Setup failed: Invalid provider') this.type = Le.video break case 'video': case 'audio': ;(this.type = n), (this.provider = Y.html5), this.media.hasAttribute('crossorigin') && (this.config.crossorigin = !0), this.media.hasAttribute('autoplay') && (this.config.autoplay = !0), (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) && (this.config.playsinline = !0), this.media.hasAttribute('muted') && (this.config.muted = !0), this.media.hasAttribute('loop') && (this.config.loop.active = !0) break default: return void this.debug.error('Setup failed: unsupported type') } ;(this.supported = x.check( this.type, this.provider, this.config.playsinline )), this.supported.api ? ((this.eventListeners = []), (this.listeners = new xi(this)), (this.storage = new ae(this)), (this.media.plyr = this), l.element(this.elements.container) || ((this.elements.container = y('div', { tabindex: 0 })), lt(this.media, this.elements.container)), P.migrateStyles.call(this), P.addStyleHook.call(this), Tt.setup.call(this), this.config.debug && C.call( this, this.elements.container, this.config.events.join(' '), o => { this.debug.log(`event: ${o.type}`) } ), (this.fullscreen = new F(this)), (this.isHTML5 || (this.isEmbed && !this.supported.ui)) && P.build.call(this), this.listeners.container(), this.listeners.global(), this.config.ads.enabled && (this.ads = new ji(this)), this.isHTML5 && this.config.autoplay && this.once('canplay', () => V(this.play())), (this.lastSeekTime = 0), this.config.previewThumbnails.enabled && (this.previewThumbnails = new Re(this))) : this.debug.error('Setup failed: no support') } get isHTML5() { return this.provider === Y.html5 } get isEmbed() { return this.isYouTube || this.isVimeo } get isYouTube() { return this.provider === Y.youtube } get isVimeo() { return this.provider === Y.vimeo } get isVideo() { return this.type === Le.video } get isAudio() { return this.type === Le.audio } get playing() { return Boolean(this.ready && !this.paused && !this.ended) } get paused() { return Boolean(this.media.paused) } get stopped() { return Boolean(this.paused && this.currentTime === 0) } get ended() { return Boolean(this.media.ended) } set currentTime(i) { if (!this.duration) return const t = l.number(i) && i > 0 ;(this.media.currentTime = t ? Math.min(i, this.duration) : 0), this.debug.log(`Seeking to ${this.currentTime} seconds`) } get currentTime() { return Number(this.media.currentTime) } get buffered() { const { buffered: i } = this.media return l.number(i) ? i : i && i.length && this.duration > 0 ? i.end(0) / this.duration : 0 } get seeking() { return Boolean(this.media.seeking) } get duration() { const i = parseFloat(this.config.duration), t = (this.media || {}).duration, s = l.number(t) && t !== 1 / 0 ? t : 0 return i || s } set volume(i) { let t = i l.string(t) && (t = Number(t)), l.number(t) || (t = this.storage.get('volume')), l.number(t) || ({ volume: t } = this.config), t > 1 && (t = 1), t < 0 && (t = 0), (this.config.volume = t), (this.media.volume = t), !l.empty(i) && this.muted && t > 0 && (this.muted = !1) } get volume() { return Number(this.media.volume) } set muted(i) { let t = i l.boolean(t) || (t = this.storage.get('muted')), l.boolean(t) || (t = this.config.muted), (this.config.muted = t), (this.media.muted = t) } get muted() { return Boolean(this.media.muted) } get hasAudio() { return ( !this.isHTML5 || !!this.isAudio || Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length) ) } set speed(i) { let t = null l.number(i) && (t = i), l.number(t) || (t = this.storage.get('speed')), l.number(t) || (t = this.config.speed.selected) const { minimumSpeed: s, maximumSpeed: n } = this ;(t = kt(t, s, n)), (this.config.speed.selected = t), setTimeout(() => { this.media && (this.media.playbackRate = t) }, 0) } get speed() { return Number(this.media.playbackRate) } get minimumSpeed() { return this.isYouTube ? Math.min(...this.options.speed) : this.isVimeo ? 0.5 : 0.0625 } get maximumSpeed() { return this.isYouTube ? Math.max(...this.options.speed) : this.isVimeo ? 2 : 16 } set quality(i) { const t = this.config.quality, s = this.options.quality if (!s.length) return let n = [ !l.empty(i) && Number(i), this.storage.get('quality'), t.selected, t.default ].find(l.number), a = !0 if (!s.includes(n)) { const r = ct(s, n) this.debug.warn(`Unsupported quality option: ${n}, using ${r} instead`), (n = r), (a = !1) } ;(t.selected = n), (this.media.quality = n), a && this.storage.set({ quality: n }) } get quality() { return this.media.quality } set loop(i) { const t = l.boolean(i) ? i : this.config.loop.active ;(this.config.loop.active = t), (this.media.loop = t) } get loop() { return Boolean(this.media.loop) } set source(i) { je.change.call(this, i) } get source() { return this.media.currentSrc } get download() { const { download: i } = this.config.urls return l.url(i) ? i : this.source } set download(i) { l.url(i) && ((this.config.urls.download = i), h.setDownloadUrl.call(this)) } set poster(i) { this.isVideo ? P.setPoster.call(this, i, !1).catch(() => {}) : this.debug.warn('Poster can only be set for video') } get poster() { return this.isVideo ? this.media.getAttribute('poster') || this.media.getAttribute('data-poster') : null } get ratio() { if (!this.isVideo) return null const i = ye(Me.call(this)) return l.array(i) ? i.join(':') : i } set ratio(i) { this.isVideo ? l.string(i) && dt(i) ? ((this.config.ratio = ye(i)), te.call(this)) : this.debug.error(`Invalid aspect ratio specified (${i})`) : this.debug.warn('Aspect ratio can only be set for video') } set autoplay(i) { this.config.autoplay = l.boolean(i) ? i : this.config.autoplay } get autoplay() { return Boolean(this.config.autoplay) } toggleCaptions(i) { E.toggle.call(this, i, !1) } set currentTrack(i) { E.set.call(this, i, !1), E.setup.call(this) } get currentTrack() { const { toggled: i, currentTrack: t } = this.captions return i ? t : -1 } set language(i) { E.setLanguage.call(this, i, !1) } get language() { return (E.getCurrentTrack.call(this) || {}).language } set pip(i) { if (!x.pip) return const t = l.boolean(i) ? i : !this.pip l.function(this.media.webkitSetPresentationMode) && this.media.webkitSetPresentationMode(t ? Ie.active : Ie.inactive), l.function(this.media.requestPictureInPicture) && (!this.pip && t ? this.media.requestPictureInPicture() : this.pip && !t && document.exitPictureInPicture()) } get pip() { return x.pip ? l.empty(this.media.webkitPresentationMode) ? this.media === document.pictureInPictureElement : this.media.webkitPresentationMode === Ie.active : null } setPreviewThumbnails(i) { this.previewThumbnails && this.previewThumbnails.loaded && (this.previewThumbnails.destroy(), (this.previewThumbnails = null)), Object.assign(this.config.previewThumbnails, i), this.config.previewThumbnails.enabled && (this.previewThumbnails = new Re(this)) } static supported(i, t, s) { return x.check(i, t, s) } static loadSprite(i, t) { return ft(i, t) } static setup(i, t = {}) { let s = null return ( l.string(i) ? (s = Array.from(document.querySelectorAll(i))) : l.nodeList(i) ? (s = Array.from(i)) : l.array(i) && (s = i.filter(l.element)), l.empty(s) ? null : s.map(n => new ce(n, t)) ) } } ce.defaults = pi(wt) var Hi = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAABSCAMAAADw8nOpAAAAAXNSR0IArs4c6QAAAapQTFRFAAAA////////////2NjY2dnZ9vb2////9vb23Nzc3d3d3t7e39/f////4+Pj4+Pj6+vr7Ozs5+fn6Ojo7u7u6enp6enp7+/v8fHx7Ozs8fHx7e3t7+/v8/Pz8PDw8/Pz9PT0+/v78PDw8PDw9PT09PT0////9fX1/Pz89fX19fX19fX18vLy/Pz89vb29vb2/Pz8+fn59/f3////9/f3+vr69/f3+vr6////+Pj4+/v7////+/v7+/v7+Pj4+fn5/////f39+/v7+/v7+/v7+fn5+/v7+/v7/f39////+/v7////+/v7/f39/Pz8/Pz8/////Pz8/////Pz8/f39/f39/Pz8/f39/v7+/Pz8/v7+/////Pz8/v7+/v7+/v7+/v7+/Pz8/v7+/////v7+/v7+/v7+/v7+/v7+/v7+/////v7+/v7+/v7+/////v7+/////v7+/v7+/////v7+/////v7+/////////////////v7+/////v7+/////////////v7+/////////////////////v7+////////////////////////lZ+FUgAAAI10Uk5TAAYSFRobGxscHR4fICMkJScpKywsLi8vNTY2OD5BQkJDQ0RGRkhISktMTlBRUlNVWFlbXF1gY29wcXJyc3R1d3p7fH+AgoSFhoaHj5CTlJWXmJifn6WoqKusr6+0tLi5ury/v8LDyMvMzdTV1tjY2trb3ODh4eLj5ejs7e3u7u/w8vT19vj5+vr7/P3+n1NMJwAAA5RJREFUWMO1metfEkEUhg86lrZZRBeVitJSsVIkKym7KFqYqJGXLiplCWUYBKllRiaQa7Lz/s998Bqyu7ML+37eeX47t3Pec4ZIR9VuX2gutpSW5fRSbC7kc1dTKaroHEtyFIgnxzorzPFs7VMbADLRCb/X5XRIksPp8vonohkAG1PtNsPAysFVIB8JtNawAtW0BiJ5YHWw0hDwaDALxAbqmIrqBmJANnhEfMq9OfDZNqaptlmOXK/g9Bvj4DNNTFdNMxzxRpFfHOFIeZiQPCnwEd0frZ2HPCQxQUlDMuZrtYkt61hsZgbUvIj1Fi1i1ybCdmZI9jA2u9SJPQpGmWGNQulRJULpZybUr0CF2aUo3cyUuhWl6NxbNtHPTKofm0X2qHbdzDrur+f6obNkm0eYlaAw5gvP/AgW7aUg7YsYKbjXXG5mJalZ5v/dd1sCQ6xEDSFxcOp9SEmlIqUU+g5E3Bz3sJLl4bn9mBzEDCuDZhDcyzNZrhpxT104Loxs4tndfDSIWbX1mdzCr8fHRJmzGNzZ7lWo5ZlhAMDna4LINqxub3o7YmrffN12A8qkQ4wZQzsREU1jQO2TH7sW4+ddIeQApomIKuR8nS4S+HBRAFmX36ggok5EmAASf5+d0GdG0ElEYwgIIYHvt3WRAYwRURKtgkjgbb0OshVJomqeqRFGIhfQPqQ1GV5Nbo2lPIwEEjd0FtNNPowbQoK/PKOBHIePQvAbQwJrD6pUR/gRojl4jSKBj5fVRngxRwtwGUdi6/nJ4iNcWKBlNJhAAis3i45owDKl4TCFRL6j2AgH0iRDMocsnvclyCUg36shTU8c99QmvgSnKWR+uOgIJ5YoZuoQ4dOV4iMuIWbuqP9+VKVx1E1cSP7qrOaFNBw28KVDI2xMwEduRA0h/2hXRVG4DYZgvDuvH4INJYqVOyKJwkA6Uw0/helMNOlqBMnCpCtoDdbuVwlbAyEDw1+cFjMwU3o269sOMX7dmM3SMIOvt5P3E0GHuWcGNSzruTiAN/VMUHuWVctYS7ceXjVjrC2w/1YUKdRbnlKq92DBFy9HwRe3WVuWWlE8W1HiW9CIsKJdYkVTx4rWkxUNMivaeFY0G61oiVrRuCWixoR4eznRKNgE7xNtgveJvwEcKXernoio8mmZHxS2nz2mZQCZyLjf62pwSJKjweX1j0cyAORpE88eljzOHHxCWlhOy3J6eUHoCekfdmynrwwsFL4AAAAASUVORK5CYII=', Ui = Nt({ name: 'col-video', props: { trySee: { type: Boolean, default: !1 }, freeTitleStatus: { type: Boolean, default: !0 }, freeRate: { type: Number, default: 100 }, setting: { type: Object, default: () => {} }, controls: Boolean, height: String, src: { type: String, default: '' }, poster: { type: String, default: '' }, styleValue: { type: Object, default: () => ({}) }, preload: { type: String, default: 'auto' }, currentTime: { type: Boolean, default: !0 }, playsinline: { type: Boolean, default: !0 }, onPlay: { type: Function, default: () => {} } }, data() { return { player: null, loading: !0, trySeeOver: !1, showSeeStatus: !0 } }, mounted() { this._init(), Lt('setVideoPlayer', e => { ;(e == null ? void 0 : e.content).status === 'pause' && this.player.pause() }) }, computed: { computedSeeStatus() { return ( console.log( this.showSeeStatus, this.trySee, this.trySeeOver, 'this.showSeeStatus, this.trySee' ), this.showSeeStatus && this.trySee ) }, playTime() { return (this.player.duration * this.freeRate) / 100 || 0 } }, methods: { _init() { const e = ['play-large', 'play', 'progress', 'captions', 'fullscreen'] this.currentTime && e.push('current-time') const i = ie(q({ controls: e }, this.setting), { invertTime: !1 }) Ot().iPhone && (i.fullscreen = { enabled: !0, fallback: 'force', iosNative: !0 }), (this.player = new ce(this.$refs.video, i)), this.player.elements.container && (this.player.elements.container.style.height = this.height || '210px'), this.preload === 'none' && (this.loading = !1), this.player.on('loadedmetadata', () => { ;(this.loading = !1), console.log('loading 1111'), this.trySee ? this.domPlayVisibility() : this.domPlayVisibility(!1) const t = this this.player.on('timeupdate', () => { const s = t.player s.currentTime >= this.playTime && t.trySee && (s.pause(), (t.trySeeOver = !0), (t.showSeeStatus = !0), t.domPlayVisibility()) }) }), this.player.on('play', () => { $t({ api: 'getDeviceStatus', content: { type: 'video' } }, t => { t.content.status == '1' && (It( '\u4E3A\u4E86\u4FDD\u8BC1\u6570\u636E\u5B89\u5168\uFF0C\u8BF7\u4E0D\u8981\u5F55\u5C4F' ), this.player.pause()) }), this.onPlay && this.onPlay() }), this.player.on('enterfullscreen', () => { console.log('fullscreen') const t = document.createElement('i') ;(t.id = 'fullscreen-back'), (t.className = 'van-icon van-icon-arrow-left video-back'), t.addEventListener('click', () => { this.player.fullscreen.exit() }), console.log(document.getElementsByClassName('plyr')), document.getElementsByClassName('plyr')[0].appendChild(t) }), this.player.on('exitfullscreen', () => { console.log('exitfullscreen') const t = document.getElementById('fullscreen-back') t && t.remove() }) }, domPlayVisibility(e = !0) { const i = document.querySelector('.plyr__controls'), t = document.querySelector('.plyr__control--overlaid') e ? (i == null || i.setAttribute('style', 'display:none'), t == null || t.setAttribute('style', 'display:none')) : (i == null || i.removeAttribute('style'), setTimeout(() => { t == null || t.removeAttribute('style') }, 200)) }, onClickPlay() { this.player.play(), this.domPlayVisibility(!1), (this.showSeeStatus = !1) }, onBuy() { this.$router.back() }, onReplay() { this.player.restart(), this.player.play(), this.domPlayVisibility(!1), (this.trySeeOver = !1), (this.showSeeStatus = !1) } }, unmounted() { var e ;(e = this.player) == null || e.destroy() }, render() { return j('div', { class: U['video-container'] }, [ j( 'video', { ref: 'video', class: U.video, src: this.src, playsinline: this.playsinline, poster: this.poster, preload: this.preload, style: q({}, this.styleValue) }, null ), this.loading && j( 'div', { class: U.loadingVideo, style: { height: this.height || '210px' } }, [ j( Mt, { size: 36, color: '#01C1B5', vertical: !0, style: { height: '100%', justifyContent: 'center' } }, { default: () => [Te('\u52A0\u8F7D\u4E2D...')] } ) ] ), this.trySee && this.computedSeeStatus && !this.loading && j( 'div', { class: [U.loadingVideo, U.playOver], style: { height: this.height || '210px' } }, [ this.trySeeOver ? j(qe, null, [ j('p', { class: U.tips }, [ this.freeTitleStatus ? '\u514D\u8D39\u8BD5\u770B\u7ED3\u675F\uFF0C\u8D2D\u4E70\u5B8C\u6574\u8BFE\u7A0B\u540E\u7EE7\u7EED\u5B66\u4E60' : '\u8BD5\u770B\u7ED3\u675F\uFF0C\u9886\u53D6\u8BFE\u7A0B\u540E\u7EE7\u7EED\u5B66\u4E60' ]), j( xt, { class: U.btn, type: 'primary', round: !0, size: 'small', onClick: this.onBuy }, { default: () => [ _t.platformType === 'STUDENT' ? this.freeTitleStatus ? '\u7ACB\u5373\u8D2D\u4E70' : '\u514D\u8D39\u9886\u53D6' : '\u8FD4\u56DE' ] } ), j('div', { class: U.replay, onClick: this.onReplay }, [ j( Ue, { name: 'replay', style: { marginRight: '5px' }, size: 16 }, null ), Te('\u91CD\u64AD') ]) ]) : j(qe, null, [ j( Ue, { name: Hi, size: 50, onClick: this.onClickPlay }, null ), j('p', { class: U.freeTxt }, [ Te('\u514D\u8D39'), this.freeTitleStatus ? '\u8BD5\u770B' : '\u9886\u53D6' ]) ]) ] ) ]) } }) export { Ui as C }