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 }