@webitel/ui-sdk 25.12.21 → 25.12.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/{install-CdGI1s_Z.js → install-Dlm9F6VX.js} +32240 -31420
  2. package/dist/plyr-C2xH9S2_.js +4350 -0
  3. package/dist/ui-sdk.css +1 -1
  4. package/dist/ui-sdk.js +1 -1
  5. package/dist/ui-sdk.umd.cjs +1453 -1358
  6. package/dist/{vidstack-Bq6c3Bam-BLAMh0vH.js → vidstack-Bq6c3Bam-LBg_N7NA.js} +29 -29
  7. package/dist/{vidstack-D2pY00kU-Dicre-nA.js → vidstack-D2pY00kU-B54jdjLZ.js} +18 -18
  8. package/dist/{vidstack-DDXt6fpN-CdAy0iv6.js → vidstack-DDXt6fpN-0R_qWhr7.js} +3 -3
  9. package/dist/{vidstack-D_-9AA6_-CidODK__.js → vidstack-D_-9AA6_-C20rEPA8.js} +1 -1
  10. package/dist/{vidstack-DqAw8m9J-BwXpv8Os.js → vidstack-DqAw8m9J-BVoQCcQn.js} +7 -7
  11. package/dist/{vidstack-audio-BQjseZWu.js → vidstack-audio-CVUfqXtN.js} +2 -2
  12. package/dist/{vidstack-dash-Cx5Y-oOT.js → vidstack-dash-DH1tKEgp.js} +3 -3
  13. package/dist/{vidstack-google-cast-DRNYogTM.js → vidstack-google-cast-Chb7A1N-.js} +33 -33
  14. package/dist/{vidstack-hls-sG3loGlT.js → vidstack-hls-isJ6fzIa.js} +3 -3
  15. package/dist/{vidstack-video-DkPlVqH9.js → vidstack-video-Oj0vav_S.js} +12 -12
  16. package/dist/{vidstack-vimeo-Cp4A_zm_.js → vidstack-vimeo-t7YlxjO1.js} +18 -18
  17. package/dist/{vidstack-youtube-CHb6qlZ2.js → vidstack-youtube-Dx4AYrj5.js} +22 -22
  18. package/package.json +4 -4
  19. package/src/components/wt-load-bar/_variables.scss +5 -1
  20. package/src/components/wt-load-bar/wt-load-bar.vue +58 -3
  21. package/src/install.ts +1 -1
  22. package/types/api/clients/media/media.d.ts +3 -3
  23. package/types/components/on-demand/wt-display-chip-items/wt-display-chip-items.vue.d.ts +2 -14
  24. package/types/components/on-demand/wt-selection-popup/wt-selection-popup.vue.d.ts +1 -0
  25. package/types/components/on-demand/wt-type-extension-value-input/wt-type-extension-value-input.vue.d.ts +2 -55
  26. package/types/components/wt-action-bar/wt-action-bar.vue.d.ts +2 -0
  27. package/types/components/wt-badge/wt-badge.vue.d.ts +1 -1
  28. package/types/components/wt-button/wt-button.vue.d.ts +2 -48
  29. package/types/components/wt-checkbox/wt-checkbox.vue.d.ts +2 -27
  30. package/types/components/wt-chip/wt-chip.vue.d.ts +2 -7
  31. package/types/components/wt-confirm-dialog/wt-confirm-dialog.vue.d.ts +1 -0
  32. package/types/components/wt-context-menu/wt-context-menu.vue.d.ts +1 -0
  33. package/types/components/wt-datepicker/wt-datepicker.vue.d.ts +4 -4
  34. package/types/components/wt-dual-panel/wt-dual-panel.vue.d.ts +3 -0
  35. package/types/components/wt-empty/wt-empty.vue.d.ts +7 -0
  36. package/types/components/wt-expansion-panel/wt-expansion-panel.vue.d.ts +2 -0
  37. package/types/components/wt-image/wt-image.vue.d.ts +2 -17
  38. package/types/components/wt-input/wt-input.vue.d.ts +4 -52
  39. package/types/components/wt-label/wt-label.vue.d.ts +2 -4
  40. package/types/components/wt-load-bar/wt-load-bar.vue.d.ts +11 -0
  41. package/types/components/wt-page-header/wt-page-header.vue.d.ts +3 -0
  42. package/types/components/wt-pagination/wt-pagination.vue.d.ts +1 -1
  43. package/types/components/wt-popover/wt-popover.vue.d.ts +2 -32
  44. package/types/components/wt-radio/wt-radio.vue.d.ts +2 -22
  45. package/types/components/wt-search-bar/wt-search-bar.vue.d.ts +2 -97
  46. package/types/components/wt-select/wt-select.vue.d.ts +4 -1
  47. package/types/components/wt-slider/wt-slider.vue.d.ts +1 -1
  48. package/types/components/wt-stepper/wt-stepper.vue.d.ts +1 -0
  49. package/types/components/wt-switcher/wt-switcher.vue.d.ts +2 -20
  50. package/types/components/wt-table/wt-table.vue.d.ts +2 -88
  51. package/types/components/wt-tags-input/wt-tags-input.vue.d.ts +4 -1
  52. package/types/components/wt-textarea/wt-textarea.vue.d.ts +4 -48
  53. package/types/components/wt-tooltip/wt-tooltip.vue.d.ts +1 -0
  54. package/types/components/wt-tree-table/wt-tree-table.vue.d.ts +2 -34
  55. package/types/components/wt-tree-table-row/wt-tree-table-row.vue.d.ts +2 -30
  56. package/types/install.d.ts +1 -1
  57. package/types/modules/Userinfo/api/userinfo.d.ts +1 -1
  58. package/types/modules/Userinfo/v2/api/UserinfoAPI.d.ts +1 -1
  59. package/dist/plyr.min-BRLz1cd6.js +0 -2260
@@ -0,0 +1,4350 @@
1
+ var gt = Object.defineProperty;
2
+ var bt = (e, t, i) => t in e ? gt(e, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : e[t] = i;
3
+ var m = (e, t, i) => bt(e, typeof t != "symbol" ? t + "" : t, i);
4
+ import { g as yt } from "./install-Dlm9F6VX.js";
5
+ function wt(e, t) {
6
+ if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function");
7
+ }
8
+ function Oe(e, t) {
9
+ for (var i = 0; i < t.length; i++) {
10
+ var n = t[i];
11
+ n.enumerable = n.enumerable || !1, n.configurable = !0, "value" in n && (n.writable = !0), Object.defineProperty(e, n.key, n);
12
+ }
13
+ }
14
+ function vt(e, t, i) {
15
+ return t && Oe(e.prototype, t), i && Oe(e, i), e;
16
+ }
17
+ function kt(e, t, i) {
18
+ return t in e ? Object.defineProperty(e, t, { value: i, enumerable: !0, configurable: !0, writable: !0 }) : e[t] = i, e;
19
+ }
20
+ function _e(e, t) {
21
+ var i = Object.keys(e);
22
+ if (Object.getOwnPropertySymbols) {
23
+ var n = Object.getOwnPropertySymbols(e);
24
+ t && (n = n.filter((function(s) {
25
+ return Object.getOwnPropertyDescriptor(e, s).enumerable;
26
+ }))), i.push.apply(i, n);
27
+ }
28
+ return i;
29
+ }
30
+ function je(e) {
31
+ for (var t = 1; t < arguments.length; t++) {
32
+ var i = arguments[t] != null ? arguments[t] : {};
33
+ t % 2 ? _e(Object(i), !0).forEach((function(n) {
34
+ kt(e, n, i[n]);
35
+ })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(i)) : _e(Object(i)).forEach((function(n) {
36
+ Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(i, n));
37
+ }));
38
+ }
39
+ return e;
40
+ }
41
+ var De = { addCSS: !0, thumbWidth: 15, watch: !0 };
42
+ function Tt(e, t) {
43
+ return (function() {
44
+ return Array.from(document.querySelectorAll(t)).includes(this);
45
+ }).call(e, t);
46
+ }
47
+ function Ct(e, t) {
48
+ if (e && t) {
49
+ var i = new Event(t, { bubbles: !0 });
50
+ e.dispatchEvent(i);
51
+ }
52
+ }
53
+ var ie = function(e) {
54
+ return e != null ? e.constructor : null;
55
+ }, Me = function(e, t) {
56
+ return !!(e && t && e instanceof t);
57
+ }, Be = function(e) {
58
+ return e == null;
59
+ }, We = function(e) {
60
+ return ie(e) === Object;
61
+ }, At = function(e) {
62
+ return ie(e) === Number && !Number.isNaN(e);
63
+ }, ze = function(e) {
64
+ return ie(e) === String;
65
+ }, Et = function(e) {
66
+ return ie(e) === Boolean;
67
+ }, St = function(e) {
68
+ return ie(e) === Function;
69
+ }, Ke = function(e) {
70
+ return Array.isArray(e);
71
+ }, Ye = function(e) {
72
+ return Me(e, NodeList);
73
+ }, Pt = function(e) {
74
+ return Me(e, Element);
75
+ }, Mt = function(e) {
76
+ return Me(e, Event);
77
+ }, Nt = function(e) {
78
+ return Be(e) || (ze(e) || Ke(e) || Ye(e)) && !e.length || We(e) && !Object.keys(e).length;
79
+ }, D = { nullOrUndefined: Be, object: We, number: At, string: ze, boolean: Et, function: St, array: Ke, nodeList: Ye, element: Pt, event: Mt, empty: Nt };
80
+ function xt(e) {
81
+ var t = "".concat(e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
82
+ return t ? Math.max(0, (t[1] ? t[1].length : 0) - (t[2] ? +t[2] : 0)) : 0;
83
+ }
84
+ function Lt(e, t) {
85
+ if (1 > t) {
86
+ var i = xt(t);
87
+ return parseFloat(e.toFixed(i));
88
+ }
89
+ return Math.round(e / t) * t;
90
+ }
91
+ var $t = (function() {
92
+ function e(t, i) {
93
+ wt(this, e), D.element(t) ? this.element = t : D.string(t) && (this.element = document.querySelector(t)), D.element(this.element) && D.empty(this.element.rangeTouch) && (this.config = je({}, De, {}, i), this.init());
94
+ }
95
+ return vt(e, [{ key: "init", value: function() {
96
+ 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);
97
+ } }, { key: "destroy", value: function() {
98
+ e.enabled && (this.config.addCSS && (this.element.style.userSelect = "", this.element.style.webKitUserSelect = "", this.element.style.touchAction = ""), this.listeners(!1), this.element.rangeTouch = null);
99
+ } }, { key: "listeners", value: function(t) {
100
+ var i = this, n = t ? "addEventListener" : "removeEventListener";
101
+ ["touchstart", "touchmove", "touchend"].forEach((function(s) {
102
+ i.element[n](s, (function(a) {
103
+ return i.set(a);
104
+ }), !1);
105
+ }));
106
+ } }, { key: "get", value: function(t) {
107
+ if (!e.enabled || !D.event(t)) return null;
108
+ var i, n = t.target, s = t.changedTouches[0], a = parseFloat(n.getAttribute("min")) || 0, l = parseFloat(n.getAttribute("max")) || 100, o = parseFloat(n.getAttribute("step")) || 1, c = n.getBoundingClientRect(), u = 100 / c.width * (this.config.thumbWidth / 2) / 100;
109
+ return 0 > (i = 100 / c.width * (s.clientX - c.left)) ? i = 0 : 100 < i && (i = 100), 50 > i ? i -= (100 - 2 * i) * u : 50 < i && (i += 2 * (i - 50) * u), a + Lt(i / 100 * (l - a), o);
110
+ } }, { key: "set", value: function(t) {
111
+ e.enabled && D.event(t) && !t.target.disabled && (t.preventDefault(), t.target.value = this.get(t), Ct(t.target, t.type === "touchend" ? "change" : "input"));
112
+ } }], [{ key: "setup", value: function(t) {
113
+ var i = 1 < arguments.length && arguments[1] !== void 0 ? arguments[1] : {}, n = null;
114
+ if (D.empty(t) || D.string(t) ? n = Array.from(document.querySelectorAll(D.string(t) ? t : 'input[type="range"]')) : D.element(t) ? n = [t] : D.nodeList(t) ? n = Array.from(t) : D.array(t) && (n = t.filter(D.element)), D.empty(n)) return null;
115
+ var s = je({}, De, {}, i);
116
+ if (D.string(t) && s.watch) {
117
+ var a = new MutationObserver((function(l) {
118
+ Array.from(l).forEach((function(o) {
119
+ Array.from(o.addedNodes).forEach((function(c) {
120
+ D.element(c) && Tt(c, t) && new e(c, s);
121
+ }));
122
+ }));
123
+ }));
124
+ a.observe(document.body, { childList: !0, subtree: !0 });
125
+ }
126
+ return n.map((function(l) {
127
+ return new e(l, i);
128
+ }));
129
+ } }, { key: "enabled", get: function() {
130
+ return "ontouchstart" in document.documentElement;
131
+ } }]), e;
132
+ })();
133
+ const se = (e) => e !== null && typeof e < "u" ? e.constructor : null, B = (e, t) => !!(e && t && e instanceof t), Ne = (e) => e === null || typeof e > "u", Xe = (e) => se(e) === Object, It = (e) => se(e) === Number && !Number.isNaN(e), pe = (e) => se(e) === String, Ot = (e) => se(e) === Boolean, Qe = (e) => typeof e == "function", Je = (e) => Array.isArray(e), _t = (e) => B(e, WeakMap), Ge = (e) => B(e, NodeList), jt = (e) => se(e) === Text, Dt = (e) => B(e, Event), Rt = (e) => B(e, KeyboardEvent), Ht = (e) => B(e, window.TextTrackCue) || B(e, window.VTTCue), qt = (e) => B(e, TextTrack) || !Ne(e) && pe(e.kind), Vt = (e) => B(e, Promise) && Qe(e.then);
134
+ function Ft(e) {
135
+ return e !== null && typeof e == "object" && e.nodeType === 1 && typeof e.style == "object" && typeof e.ownerDocument == "object";
136
+ }
137
+ function Ze(e) {
138
+ return Ne(e) || (pe(e) || Je(e) || Ge(e)) && !e.length || Xe(e) && !Object.keys(e).length;
139
+ }
140
+ function Ut(e) {
141
+ if (B(e, window.URL))
142
+ return !0;
143
+ if (!pe(e))
144
+ return !1;
145
+ let t = e;
146
+ (!e.startsWith("http://") || !e.startsWith("https://")) && (t = `http://${e}`);
147
+ try {
148
+ return !Ze(new URL(t).hostname);
149
+ } catch {
150
+ return !1;
151
+ }
152
+ }
153
+ const r = {
154
+ nullOrUndefined: Ne,
155
+ object: Xe,
156
+ number: It,
157
+ string: pe,
158
+ boolean: Ot,
159
+ function: Qe,
160
+ array: Je,
161
+ weakMap: _t,
162
+ nodeList: Ge,
163
+ element: Ft,
164
+ textNode: jt,
165
+ event: Dt,
166
+ keyboardEvent: Rt,
167
+ cue: Ht,
168
+ track: qt,
169
+ promise: Vt,
170
+ url: Ut,
171
+ empty: Ze
172
+ }, ke = (() => {
173
+ const e = document.createElement("span"), t = {
174
+ WebkitTransition: "webkitTransitionEnd",
175
+ MozTransition: "transitionend",
176
+ OTransition: "oTransitionEnd otransitionend",
177
+ transition: "transitionend"
178
+ }, i = Object.keys(t).find((n) => e.style[n] !== void 0);
179
+ return r.string(i) ? t[i] : !1;
180
+ })();
181
+ function et(e, t) {
182
+ setTimeout(() => {
183
+ try {
184
+ e.hidden = !0, e.offsetHeight, e.hidden = !1;
185
+ } catch {
186
+ }
187
+ }, t);
188
+ }
189
+ function Bt(e) {
190
+ return JSON.parse(JSON.stringify(e));
191
+ }
192
+ function tt(e, t) {
193
+ return t.split(".").reduce((i, n) => i && i[n], e);
194
+ }
195
+ function L(e = {}, ...t) {
196
+ if (!t.length)
197
+ return e;
198
+ const i = t.shift();
199
+ return r.object(i) ? (Object.keys(i).forEach((n) => {
200
+ r.object(i[n]) ? (Object.keys(e).includes(n) || Object.assign(e, { [n]: {} }), L(e[n], i[n])) : Object.assign(e, { [n]: i[n] });
201
+ }), L(e, ...t)) : e;
202
+ }
203
+ function it(e, t) {
204
+ const i = e.length ? e : [e];
205
+ Array.from(i).reverse().forEach((n, s) => {
206
+ const a = s > 0 ? t.cloneNode(!0) : t, l = n.parentNode, o = n.nextSibling;
207
+ a.appendChild(n), o ? l.insertBefore(a, o) : l.appendChild(a);
208
+ });
209
+ }
210
+ function Te(e, t) {
211
+ !r.element(e) || r.empty(t) || Object.entries(t).filter(([, i]) => !r.nullOrUndefined(i)).forEach(([i, n]) => e.setAttribute(i, n));
212
+ }
213
+ function b(e, t, i) {
214
+ const n = document.createElement(e);
215
+ return r.object(t) && Te(n, t), r.string(i) && (n.textContent = i), n;
216
+ }
217
+ function Wt(e, t) {
218
+ !r.element(e) || !r.element(t) || t.parentNode.insertBefore(e, t.nextSibling);
219
+ }
220
+ function Re(e, t, i, n) {
221
+ r.element(t) && t.appendChild(b(e, i, n));
222
+ }
223
+ function U(e) {
224
+ if (r.nodeList(e) || r.array(e)) {
225
+ Array.from(e).forEach(U);
226
+ return;
227
+ }
228
+ !r.element(e) || !r.element(e.parentNode) || e.parentNode.removeChild(e);
229
+ }
230
+ function ae(e) {
231
+ if (!r.element(e)) return;
232
+ let { length: t } = e.childNodes;
233
+ for (; t > 0; )
234
+ e.removeChild(e.lastChild), t -= 1;
235
+ }
236
+ function ue(e, t) {
237
+ return !r.element(t) || !r.element(t.parentNode) || !r.element(e) ? null : (t.parentNode.replaceChild(e, t), e);
238
+ }
239
+ function V(e, t) {
240
+ if (!r.string(e) || r.empty(e)) return {};
241
+ const i = {}, n = L({}, t);
242
+ return e.split(",").forEach((s) => {
243
+ const a = s.trim(), l = a.replace(".", ""), c = a.replace(/[[\]]/g, "").split("="), [u] = c, f = c.length > 1 ? c[1].replace(/["']/g, "") : "";
244
+ switch (a.charAt(0)) {
245
+ case ".":
246
+ r.string(n.class) ? i.class = `${n.class} ${l}` : i.class = l;
247
+ break;
248
+ case "#":
249
+ i.id = a.replace("#", "");
250
+ break;
251
+ case "[":
252
+ i[u] = f;
253
+ break;
254
+ }
255
+ }), L(n, i);
256
+ }
257
+ function K(e, t) {
258
+ if (!r.element(e)) return;
259
+ let i = t;
260
+ r.boolean(i) || (i = !e.hidden), e.hidden = i;
261
+ }
262
+ function E(e, t, i) {
263
+ if (r.nodeList(e))
264
+ return Array.from(e).map((n) => E(n, t, i));
265
+ if (r.element(e)) {
266
+ let n = "toggle";
267
+ return typeof i < "u" && (n = i ? "add" : "remove"), e.classList[n](t), e.classList.contains(t);
268
+ }
269
+ return !1;
270
+ }
271
+ function he(e, t) {
272
+ return r.element(e) && e.classList.contains(t);
273
+ }
274
+ function Y(e, t) {
275
+ const { prototype: i } = Element;
276
+ function n() {
277
+ return Array.from(document.querySelectorAll(t)).includes(this);
278
+ }
279
+ return (i.matches || i.webkitMatchesSelector || i.mozMatchesSelector || i.msMatchesSelector || n).call(e, t);
280
+ }
281
+ function zt(e, t) {
282
+ const { prototype: i } = Element;
283
+ function n() {
284
+ let a = this;
285
+ do {
286
+ if (Y.matches(a, t)) return a;
287
+ a = a.parentElement || a.parentNode;
288
+ } while (a !== null && a.nodeType === 1);
289
+ return null;
290
+ }
291
+ return (i.closest || n).call(e, t);
292
+ }
293
+ function Z(e) {
294
+ return this.elements.container.querySelectorAll(e);
295
+ }
296
+ function I(e) {
297
+ return this.elements.container.querySelector(e);
298
+ }
299
+ function be(e = null, t = !1) {
300
+ r.element(e) && e.focus({ preventScroll: !0, focusVisible: t });
301
+ }
302
+ const He = {
303
+ "audio/ogg": "vorbis",
304
+ "audio/wav": "1",
305
+ "video/webm": "vp8, vorbis",
306
+ "video/mp4": "avc1.42E01E, mp4a.40.2",
307
+ "video/ogg": "theora"
308
+ }, $ = {
309
+ // Basic support
310
+ audio: "canPlayType" in document.createElement("audio"),
311
+ video: "canPlayType" in document.createElement("video"),
312
+ // Check for support
313
+ // Basic functionality vs full UI
314
+ check(e, t) {
315
+ const i = $[e] || t !== "html5", n = i && $.rangeInput;
316
+ return {
317
+ api: i,
318
+ ui: n
319
+ };
320
+ },
321
+ // Picture-in-picture support
322
+ pip: document.pictureInPictureEnabled && !b("video").disablePictureInPicture,
323
+ // Airplay support
324
+ // Safari only currently
325
+ airplay: r.function(window.WebKitPlaybackTargetAvailabilityEvent),
326
+ // Inline playback support
327
+ // https://webkit.org/blog/6784/new-video-policies-for-ios/
328
+ playsinline: "playsInline" in document.createElement("video"),
329
+ // Check for mime type support against a player instance
330
+ // Credits: http://diveintohtml5.info/everything.html
331
+ // Related: http://www.leanbackplayer.com/test/h5mt.html
332
+ mime(e) {
333
+ if (r.empty(e))
334
+ return !1;
335
+ const [t] = e.split("/");
336
+ let i = e;
337
+ if (!this.isHTML5 || t !== this.type)
338
+ return !1;
339
+ Object.keys(He).includes(i) && (i += `; codecs="${He[e]}"`);
340
+ try {
341
+ return !!(i && this.media.canPlayType(i).replace(/no/, ""));
342
+ } catch {
343
+ return !1;
344
+ }
345
+ },
346
+ // Check for textTracks support
347
+ textTracks: "textTracks" in document.createElement("video"),
348
+ // <input type="range"> Sliders
349
+ rangeInput: (() => {
350
+ const e = document.createElement("input");
351
+ return e.type = "range", e.type === "range";
352
+ })(),
353
+ // Touch
354
+ // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event
355
+ touch: "ontouchstart" in document.documentElement,
356
+ // Detect transitions support
357
+ transitions: ke !== !1,
358
+ // Reduced motion iOS & MacOS setting
359
+ // https://webkit.org/blog/7551/responsive-design-for-motion/
360
+ reducedMotion: "matchMedia" in window && window.matchMedia("(prefers-reduced-motion)").matches
361
+ }, Kt = (() => {
362
+ let e = !1;
363
+ try {
364
+ const t = Object.defineProperty({}, "passive", {
365
+ get() {
366
+ return e = !0, null;
367
+ }
368
+ });
369
+ window.addEventListener("test", null, t), window.removeEventListener("test", null, t);
370
+ } catch {
371
+ }
372
+ return e;
373
+ })();
374
+ function ee(e, t, i, n = !1, s = !0, a = !1) {
375
+ if (!e || !("addEventListener" in e) || r.empty(t) || !r.function(i))
376
+ return;
377
+ const l = t.split(" ");
378
+ let o = a;
379
+ Kt && (o = {
380
+ // Whether the listener can be passive (i.e. default never prevented)
381
+ passive: s,
382
+ // Whether the listener is a capturing listener or not
383
+ capture: a
384
+ }), l.forEach((c) => {
385
+ this && this.eventListeners && n && this.eventListeners.push({ element: e, type: c, callback: i, options: o }), e[n ? "addEventListener" : "removeEventListener"](c, i, o);
386
+ });
387
+ }
388
+ function T(e, t = "", i, n = !0, s = !1) {
389
+ ee.call(this, e, t, i, !0, n, s);
390
+ }
391
+ function fe(e, t = "", i, n = !0, s = !1) {
392
+ ee.call(this, e, t, i, !1, n, s);
393
+ }
394
+ function xe(e, t = "", i, n = !0, s = !1) {
395
+ const a = (...l) => {
396
+ fe(e, t, a, n, s), i.apply(this, l);
397
+ };
398
+ ee.call(this, e, t, a, !0, n, s);
399
+ }
400
+ function y(e, t = "", i = !1, n = {}) {
401
+ if (!r.element(e) || r.empty(t))
402
+ return;
403
+ const s = new CustomEvent(t, {
404
+ bubbles: i,
405
+ detail: { ...n, plyr: this }
406
+ });
407
+ e.dispatchEvent(s);
408
+ }
409
+ function Yt() {
410
+ this && this.eventListeners && (this.eventListeners.forEach((e) => {
411
+ const { element: t, type: i, callback: n, options: s } = e;
412
+ t.removeEventListener(i, n, s);
413
+ }), this.eventListeners = []);
414
+ }
415
+ function Xt() {
416
+ return new Promise(
417
+ (e) => this.ready ? setTimeout(e, 0) : T.call(this, this.elements.container, "ready", e)
418
+ ).then(() => {
419
+ });
420
+ }
421
+ function F(e) {
422
+ r.promise(e) && e.then(null, () => {
423
+ });
424
+ }
425
+ function Ce(e) {
426
+ return r.array(e) ? e.filter((t, i) => e.indexOf(t) === i) : e;
427
+ }
428
+ function st(e, t) {
429
+ return !r.array(e) || !e.length ? null : e.reduce((i, n) => Math.abs(n - t) < Math.abs(i - t) ? n : i);
430
+ }
431
+ function nt(e) {
432
+ return !window || !window.CSS ? !1 : window.CSS.supports(e);
433
+ }
434
+ const qe = [
435
+ [1, 1],
436
+ [4, 3],
437
+ [3, 4],
438
+ [5, 4],
439
+ [4, 5],
440
+ [3, 2],
441
+ [2, 3],
442
+ [16, 10],
443
+ [10, 16],
444
+ [16, 9],
445
+ [9, 16],
446
+ [21, 9],
447
+ [9, 21],
448
+ [32, 9],
449
+ [9, 32]
450
+ ].reduce((e, [t, i]) => ({ ...e, [t / i]: [t, i] }), {});
451
+ function rt(e) {
452
+ return !r.array(e) && (!r.string(e) || !e.includes(":")) ? !1 : (r.array(e) ? e : e.split(":")).map(Number).every(r.number);
453
+ }
454
+ function de(e) {
455
+ if (!r.array(e) || !e.every(r.number))
456
+ return null;
457
+ const [t, i] = e, n = (a, l) => l === 0 ? a : n(l, a % l), s = n(t, i);
458
+ return [t / s, i / s];
459
+ }
460
+ function Le(e) {
461
+ const t = (n) => rt(n) ? n.split(":").map(Number) : null;
462
+ let i = t(e);
463
+ if (i === null && (i = t(this.config.ratio)), i === null && !r.empty(this.embed) && r.array(this.embed.ratio) && ({ ratio: i } = this.embed), i === null && this.isHTML5) {
464
+ const { videoWidth: n, videoHeight: s } = this.media;
465
+ i = [n, s];
466
+ }
467
+ return de(i);
468
+ }
469
+ function X(e) {
470
+ if (!this.isVideo)
471
+ return {};
472
+ const { wrapper: t } = this.elements, i = Le.call(this, e);
473
+ if (!r.array(i))
474
+ return {};
475
+ const [n, s] = de(i), a = nt(`aspect-ratio: ${n}/${s}`), l = 100 / n * s;
476
+ if (a ? t.style.aspectRatio = `${n}/${s}` : t.style.paddingBottom = `${l}%`, this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
477
+ const o = 100 / this.media.offsetWidth * Number.parseInt(window.getComputedStyle(this.media).paddingBottom, 10), c = (o - l) / (o / 50);
478
+ this.fullscreen.active ? t.style.paddingBottom = null : this.media.style.transform = `translateY(-${c}%)`;
479
+ } else this.isHTML5 && t.classList.add(this.config.classNames.videoFixedRatio);
480
+ return { padding: l, ratio: i };
481
+ }
482
+ function at(e, t, i = 0.05) {
483
+ const n = e / t, s = st(Object.keys(qe), n);
484
+ return Math.abs(s - n) <= i ? qe[s] : [e, t];
485
+ }
486
+ function Qt() {
487
+ const e = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0), t = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
488
+ return [e, t];
489
+ }
490
+ const z = {
491
+ getSources() {
492
+ return this.isHTML5 ? Array.from(this.media.querySelectorAll("source")).filter((t) => {
493
+ const i = t.getAttribute("type");
494
+ return r.empty(i) ? !0 : $.mime.call(this, i);
495
+ }) : [];
496
+ },
497
+ // Get quality levels
498
+ getQualityOptions() {
499
+ return this.config.quality.forced ? this.config.quality.options : z.getSources.call(this).map((e) => Number(e.getAttribute("size"))).filter(Boolean);
500
+ },
501
+ setup() {
502
+ if (!this.isHTML5)
503
+ return;
504
+ const e = this;
505
+ e.options.speed = e.config.speed.options, r.empty(this.config.ratio) || X.call(e), Object.defineProperty(e.media, "quality", {
506
+ get() {
507
+ const i = z.getSources.call(e).find((n) => n.getAttribute("src") === e.source);
508
+ return i && Number(i.getAttribute("size"));
509
+ },
510
+ set(t) {
511
+ if (e.quality !== t) {
512
+ if (e.config.quality.forced && r.function(e.config.quality.onChange))
513
+ e.config.quality.onChange(t);
514
+ else {
515
+ const n = z.getSources.call(e).find((u) => Number(u.getAttribute("size")) === t);
516
+ if (!n)
517
+ return;
518
+ const { currentTime: s, paused: a, preload: l, readyState: o, playbackRate: c } = e.media;
519
+ e.media.src = n.getAttribute("src"), (l !== "none" || o) && (e.once("loadedmetadata", () => {
520
+ e.speed = c, e.currentTime = s, a || F(e.play());
521
+ }), e.media.load());
522
+ }
523
+ y.call(e, e.media, "qualitychange", !1, {
524
+ quality: t
525
+ });
526
+ }
527
+ }
528
+ });
529
+ },
530
+ // Cancel current network requests
531
+ // See https://github.com/sampotts/plyr/issues/174
532
+ cancelRequests() {
533
+ this.isHTML5 && (U(z.getSources.call(this)), this.media.setAttribute("src", this.config.blankVideo), this.media.load(), this.debug.log("Cancelled network requests"));
534
+ }
535
+ }, Jt = !!window.document.documentMode, Gt = /Edge/.test(navigator.userAgent), Zt = "WebkitAppearance" in document.documentElement.style && !/Edge/.test(navigator.userAgent), ei = navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1, ti = /iPad|iPhone|iPod/i.test(navigator.userAgent) && navigator.maxTouchPoints > 1, _ = {
536
+ isIE: Jt,
537
+ isEdge: Gt,
538
+ isWebKit: Zt,
539
+ isIPadOS: ei,
540
+ isIos: ti
541
+ };
542
+ function ii(e) {
543
+ return `${e}-${Math.floor(Math.random() * 1e4)}`;
544
+ }
545
+ function Ae(e, ...t) {
546
+ return r.empty(e) ? e : e.toString().replace(/\{(\d+)\}/g, (i, n) => t[n].toString());
547
+ }
548
+ function si(e, t) {
549
+ return e === 0 || t === 0 || Number.isNaN(e) || Number.isNaN(t) ? 0 : (e / t * 100).toFixed(2);
550
+ }
551
+ function G(e = "", t = "", i = "") {
552
+ return e.replace(new RegExp(t.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, "\\$1"), "g"), i.toString());
553
+ }
554
+ function lt(e = "") {
555
+ return e.toString().replace(/\w\S*/g, (t) => t.charAt(0).toUpperCase() + t.slice(1).toLowerCase());
556
+ }
557
+ function ni(e = "") {
558
+ let t = e.toString();
559
+ return t = G(t, "-", " "), t = G(t, "_", " "), t = lt(t), G(t, " ", "");
560
+ }
561
+ function ri(e = "") {
562
+ let t = e.toString();
563
+ return t = ni(t), t.charAt(0).toLowerCase() + t.slice(1);
564
+ }
565
+ function ai(e) {
566
+ const t = document.createDocumentFragment(), i = document.createElement("div");
567
+ return t.appendChild(i), i.innerHTML = e, t.firstChild.textContent;
568
+ }
569
+ function li(e) {
570
+ const t = document.createElement("div");
571
+ return t.appendChild(e), t.innerHTML;
572
+ }
573
+ const Ve = {
574
+ pip: "PIP",
575
+ airplay: "AirPlay",
576
+ html5: "HTML5",
577
+ vimeo: "Vimeo",
578
+ youtube: "YouTube"
579
+ }, O = {
580
+ get(e = "", t = {}) {
581
+ if (r.empty(e) || r.empty(t))
582
+ return "";
583
+ let i = tt(t.i18n, e);
584
+ if (r.empty(i))
585
+ return Object.keys(Ve).includes(e) ? Ve[e] : "";
586
+ const n = {
587
+ "{seektime}": t.seekTime,
588
+ "{title}": t.title
589
+ };
590
+ return Object.entries(n).forEach(([s, a]) => {
591
+ i = G(i, s, a);
592
+ }), i;
593
+ }
594
+ };
595
+ class te {
596
+ constructor(t) {
597
+ m(this, "get", (t) => {
598
+ if (!te.supported || !this.enabled)
599
+ return null;
600
+ const i = window.localStorage.getItem(this.key);
601
+ if (r.empty(i)) return null;
602
+ const n = JSON.parse(i);
603
+ return r.string(t) && t.length ? n[t] : n;
604
+ });
605
+ m(this, "set", (t) => {
606
+ if (!te.supported || !this.enabled || !r.object(t))
607
+ return;
608
+ let i = this.get();
609
+ r.empty(i) && (i = {}), L(i, t);
610
+ try {
611
+ window.localStorage.setItem(this.key, JSON.stringify(i));
612
+ } catch {
613
+ }
614
+ });
615
+ this.enabled = t.config.storage.enabled, this.key = t.config.storage.key;
616
+ }
617
+ // Check for actual support (see if we can use it)
618
+ static get supported() {
619
+ try {
620
+ if (!("localStorage" in window)) return !1;
621
+ const t = "___test";
622
+ return window.localStorage.setItem(t, t), window.localStorage.removeItem(t), !0;
623
+ } catch {
624
+ return !1;
625
+ }
626
+ }
627
+ }
628
+ function ne(e, t = "text", i = !1) {
629
+ return new Promise((n, s) => {
630
+ try {
631
+ const a = new XMLHttpRequest();
632
+ if (!("withCredentials" in a)) return;
633
+ i && (a.withCredentials = !0), a.addEventListener("load", () => {
634
+ if (t === "text")
635
+ try {
636
+ n(JSON.parse(a.responseText));
637
+ } catch {
638
+ n(a.responseText);
639
+ }
640
+ else
641
+ n(a.response);
642
+ }), a.addEventListener("error", () => {
643
+ throw new Error(a.status);
644
+ }), a.open("GET", e, !0), a.responseType = t, a.send();
645
+ } catch (a) {
646
+ s(a);
647
+ }
648
+ });
649
+ }
650
+ function ot(e, t) {
651
+ if (!r.string(e))
652
+ return;
653
+ const i = "cache", n = r.string(t);
654
+ let s = !1;
655
+ const a = () => document.getElementById(t) !== null, l = (o, c) => {
656
+ o.innerHTML = c, !(n && a()) && document.body.insertAdjacentElement("afterbegin", o);
657
+ };
658
+ if (!n || !a()) {
659
+ const o = te.supported, c = document.createElement("div");
660
+ if (c.setAttribute("hidden", ""), n && c.setAttribute("id", t), o) {
661
+ const u = window.localStorage.getItem(`${i}-${t}`);
662
+ if (s = u !== null, s) {
663
+ const f = JSON.parse(u);
664
+ l(c, f.content);
665
+ }
666
+ }
667
+ ne(e).then((u) => {
668
+ if (!r.empty(u)) {
669
+ if (o)
670
+ try {
671
+ window.localStorage.setItem(
672
+ `${i}-${t}`,
673
+ JSON.stringify({
674
+ content: u
675
+ })
676
+ );
677
+ } catch {
678
+ }
679
+ l(c, u);
680
+ }
681
+ }).catch(() => {
682
+ });
683
+ }
684
+ }
685
+ const ct = (e) => Math.trunc(e / 60 / 60 % 60, 10), oi = (e) => Math.trunc(e / 60 % 60, 10), ci = (e) => Math.trunc(e % 60, 10);
686
+ function ge(e = 0, t = !1, i = !1) {
687
+ if (!r.number(e))
688
+ return ge(void 0, t, i);
689
+ const n = (o) => `0${o}`.slice(-2);
690
+ let s = ct(e);
691
+ const a = oi(e), l = ci(e);
692
+ return t || s > 0 ? s = `${s}:` : s = "", `${i && e > 0 ? "-" : ""}${s}${n(a)}:${n(l)}`;
693
+ }
694
+ const d = {
695
+ // Get icon URL
696
+ getIconUrl() {
697
+ const e = new URL(this.config.iconUrl, window.location), t = window.location.host ? window.location.host : window.top.location.host, i = e.host !== t || _.isIE && !window.svg4everybody;
698
+ return {
699
+ url: this.config.iconUrl,
700
+ cors: i
701
+ };
702
+ },
703
+ // Find the UI controls
704
+ findElements() {
705
+ try {
706
+ return this.elements.controls = I.call(this, this.config.selectors.controls.wrapper), this.elements.buttons = {
707
+ play: Z.call(this, this.config.selectors.buttons.play),
708
+ pause: I.call(this, this.config.selectors.buttons.pause),
709
+ restart: I.call(this, this.config.selectors.buttons.restart),
710
+ rewind: I.call(this, this.config.selectors.buttons.rewind),
711
+ fastForward: I.call(this, this.config.selectors.buttons.fastForward),
712
+ mute: I.call(this, this.config.selectors.buttons.mute),
713
+ pip: I.call(this, this.config.selectors.buttons.pip),
714
+ airplay: I.call(this, this.config.selectors.buttons.airplay),
715
+ settings: I.call(this, this.config.selectors.buttons.settings),
716
+ captions: I.call(this, this.config.selectors.buttons.captions),
717
+ fullscreen: I.call(this, this.config.selectors.buttons.fullscreen)
718
+ }, this.elements.progress = I.call(this, this.config.selectors.progress), this.elements.inputs = {
719
+ seek: I.call(this, this.config.selectors.inputs.seek),
720
+ volume: I.call(this, this.config.selectors.inputs.volume)
721
+ }, this.elements.display = {
722
+ buffer: I.call(this, this.config.selectors.display.buffer),
723
+ currentTime: I.call(this, this.config.selectors.display.currentTime),
724
+ duration: I.call(this, this.config.selectors.display.duration)
725
+ }, r.element(this.elements.progress) && (this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`)), !0;
726
+ } catch (e) {
727
+ return this.debug.warn("It looks like there is a problem with your custom controls HTML", e), this.toggleNativeControls(!0), !1;
728
+ }
729
+ },
730
+ // Create <svg> icon
731
+ createIcon(e, t) {
732
+ const i = "http://www.w3.org/2000/svg", n = d.getIconUrl.call(this), s = `${n.cors ? "" : n.url}#${this.config.iconPrefix}`, a = document.createElementNS(i, "svg");
733
+ Te(
734
+ a,
735
+ L(t, {
736
+ "aria-hidden": "true",
737
+ focusable: "false"
738
+ })
739
+ );
740
+ const l = document.createElementNS(i, "use"), o = `${s}-${e}`;
741
+ return "href" in l && l.setAttributeNS("http://www.w3.org/1999/xlink", "href", o), l.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", o), a.appendChild(l), a;
742
+ },
743
+ // Create hidden text label
744
+ createLabel(e, t = {}) {
745
+ const i = O.get(e, this.config), n = { ...t, class: [t.class, this.config.classNames.hidden].filter(Boolean).join(" ") };
746
+ return b("span", n, i);
747
+ },
748
+ // Create a badge
749
+ createBadge(e) {
750
+ if (r.empty(e))
751
+ return null;
752
+ const t = b("span", {
753
+ class: this.config.classNames.menu.value
754
+ });
755
+ return t.appendChild(
756
+ b(
757
+ "span",
758
+ {
759
+ class: this.config.classNames.menu.badge
760
+ },
761
+ e
762
+ )
763
+ ), t;
764
+ },
765
+ // Create a <button>
766
+ createButton(e, t) {
767
+ const i = L({}, t);
768
+ let n = ri(e);
769
+ const s = {
770
+ element: "button",
771
+ toggle: !1,
772
+ label: null,
773
+ icon: null,
774
+ labelPressed: null,
775
+ iconPressed: null
776
+ };
777
+ switch (["element", "icon", "label"].forEach((l) => {
778
+ Object.keys(i).includes(l) && (s[l] = i[l], delete i[l]);
779
+ }), s.element === "button" && !Object.keys(i).includes("type") && (i.type = "button"), Object.keys(i).includes("class") ? i.class.split(" ").includes(this.config.classNames.control) || L(i, {
780
+ class: `${i.class} ${this.config.classNames.control}`
781
+ }) : i.class = this.config.classNames.control, e) {
782
+ case "play":
783
+ s.toggle = !0, s.label = "play", s.labelPressed = "pause", s.icon = "play", s.iconPressed = "pause";
784
+ break;
785
+ case "mute":
786
+ s.toggle = !0, s.label = "mute", s.labelPressed = "unmute", s.icon = "volume", s.iconPressed = "muted";
787
+ break;
788
+ case "captions":
789
+ s.toggle = !0, s.label = "enableCaptions", s.labelPressed = "disableCaptions", s.icon = "captions-off", s.iconPressed = "captions-on";
790
+ break;
791
+ case "fullscreen":
792
+ s.toggle = !0, s.label = "enterFullscreen", s.labelPressed = "exitFullscreen", s.icon = "enter-fullscreen", s.iconPressed = "exit-fullscreen";
793
+ break;
794
+ case "play-large":
795
+ i.class += ` ${this.config.classNames.control}--overlaid`, n = "play", s.label = "play", s.icon = "play";
796
+ break;
797
+ default:
798
+ r.empty(s.label) && (s.label = n), r.empty(s.icon) && (s.icon = e);
799
+ }
800
+ const a = b(s.element);
801
+ return s.toggle ? (a.appendChild(
802
+ d.createIcon.call(this, s.iconPressed, {
803
+ class: "icon--pressed"
804
+ })
805
+ ), a.appendChild(
806
+ d.createIcon.call(this, s.icon, {
807
+ class: "icon--not-pressed"
808
+ })
809
+ ), a.appendChild(
810
+ d.createLabel.call(this, s.labelPressed, {
811
+ class: "label--pressed"
812
+ })
813
+ ), a.appendChild(
814
+ d.createLabel.call(this, s.label, {
815
+ class: "label--not-pressed"
816
+ })
817
+ )) : (a.appendChild(d.createIcon.call(this, s.icon)), a.appendChild(d.createLabel.call(this, s.label))), L(i, V(this.config.selectors.buttons[n], i)), Te(a, i), n === "play" ? (r.array(this.elements.buttons[n]) || (this.elements.buttons[n] = []), this.elements.buttons[n].push(a)) : this.elements.buttons[n] = a, a;
818
+ },
819
+ // Create an <input type='range'>
820
+ createRange(e, t) {
821
+ const i = b(
822
+ "input",
823
+ L(
824
+ V(this.config.selectors.inputs[e]),
825
+ {
826
+ type: "range",
827
+ min: 0,
828
+ max: 100,
829
+ step: 0.01,
830
+ value: 0,
831
+ autocomplete: "off",
832
+ // A11y fixes for https://github.com/sampotts/plyr/issues/905
833
+ role: "slider",
834
+ "aria-label": O.get(e, this.config),
835
+ "aria-valuemin": 0,
836
+ "aria-valuemax": 100,
837
+ "aria-valuenow": 0
838
+ },
839
+ t
840
+ )
841
+ );
842
+ return this.elements.inputs[e] = i, d.updateRangeFill.call(this, i), $t.setup(i), i;
843
+ },
844
+ // Create a <progress>
845
+ createProgress(e, t) {
846
+ const i = b(
847
+ "progress",
848
+ L(
849
+ V(this.config.selectors.display[e]),
850
+ {
851
+ min: 0,
852
+ max: 100,
853
+ value: 0,
854
+ role: "progressbar",
855
+ "aria-hidden": !0
856
+ },
857
+ t
858
+ )
859
+ );
860
+ if (e !== "volume") {
861
+ i.appendChild(b("span", null, "0"));
862
+ const n = {
863
+ played: "played",
864
+ buffer: "buffered"
865
+ }[e], s = n ? O.get(n, this.config) : "";
866
+ i.textContent = `% ${s.toLowerCase()}`;
867
+ }
868
+ return this.elements.display[e] = i, i;
869
+ },
870
+ // Create time display
871
+ createTime(e, t) {
872
+ const i = V(this.config.selectors.display[e], t), n = b(
873
+ "div",
874
+ L(i, {
875
+ class: `${i.class ? i.class : ""} ${this.config.classNames.display.time} `.trim(),
876
+ "aria-label": O.get(e, this.config),
877
+ role: "timer"
878
+ }),
879
+ "00:00"
880
+ );
881
+ return this.elements.display[e] = n, n;
882
+ },
883
+ // Bind keyboard shortcuts for a menu item
884
+ // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus
885
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143
886
+ bindMenuItemShortcuts(e, t) {
887
+ T.call(
888
+ this,
889
+ e,
890
+ "keydown keyup",
891
+ (i) => {
892
+ if (![" ", "ArrowUp", "ArrowDown", "ArrowRight"].includes(i.key) || (i.preventDefault(), i.stopPropagation(), i.type === "keydown"))
893
+ return;
894
+ const n = Y(e, '[role="menuitemradio"]');
895
+ if (!n && [" ", "ArrowRight"].includes(i.key))
896
+ d.showMenuPanel.call(this, t, !0);
897
+ else {
898
+ let s;
899
+ i.key !== " " && (i.key === "ArrowDown" || n && i.key === "ArrowRight" ? (s = e.nextElementSibling, r.element(s) || (s = e.parentNode.firstElementChild)) : (s = e.previousElementSibling, r.element(s) || (s = e.parentNode.lastElementChild)), be.call(this, s, !0));
900
+ }
901
+ },
902
+ !1
903
+ ), T.call(this, e, "keyup", (i) => {
904
+ i.key === "Return" && d.focusFirstMenuItem.call(this, null, !0);
905
+ });
906
+ },
907
+ // Create a settings menu item
908
+ createMenuItem({ value: e, list: t, type: i, title: n, badge: s = null, checked: a = !1 }) {
909
+ const l = V(this.config.selectors.inputs[i]), o = b(
910
+ "button",
911
+ L(l, {
912
+ type: "button",
913
+ role: "menuitemradio",
914
+ class: `${this.config.classNames.control} ${l.class ? l.class : ""}`.trim(),
915
+ "aria-checked": a,
916
+ value: e
917
+ })
918
+ ), c = b("span");
919
+ c.innerHTML = n, r.element(s) && c.appendChild(s), o.appendChild(c), Object.defineProperty(o, "checked", {
920
+ enumerable: !0,
921
+ get() {
922
+ return o.getAttribute("aria-checked") === "true";
923
+ },
924
+ set(u) {
925
+ u && Array.from(o.parentNode.children).filter((f) => Y(f, '[role="menuitemradio"]')).forEach((f) => f.setAttribute("aria-checked", "false")), o.setAttribute("aria-checked", u ? "true" : "false");
926
+ }
927
+ }), this.listeners.bind(
928
+ o,
929
+ "click keyup",
930
+ (u) => {
931
+ if (!(r.keyboardEvent(u) && u.key !== " ")) {
932
+ switch (u.preventDefault(), u.stopPropagation(), o.checked = !0, i) {
933
+ case "language":
934
+ this.currentTrack = Number(e);
935
+ break;
936
+ case "quality":
937
+ this.quality = e;
938
+ break;
939
+ case "speed":
940
+ this.speed = Number.parseFloat(e);
941
+ break;
942
+ }
943
+ d.showMenuPanel.call(this, "home", r.keyboardEvent(u));
944
+ }
945
+ },
946
+ i,
947
+ !1
948
+ ), d.bindMenuItemShortcuts.call(this, o, i), t.appendChild(o);
949
+ },
950
+ // Format a time for display
951
+ formatTime(e = 0, t = !1) {
952
+ if (!r.number(e))
953
+ return e;
954
+ const i = ct(this.duration) > 0;
955
+ return ge(e, i, t);
956
+ },
957
+ // Update the displayed time
958
+ updateTimeDisplay(e = null, t = 0, i = !1) {
959
+ !r.element(e) || !r.number(t) || (e.textContent = d.formatTime(t, i));
960
+ },
961
+ // Update volume UI and storage
962
+ updateVolume() {
963
+ this.supported.ui && (r.element(this.elements.inputs.volume) && d.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume), r.element(this.elements.buttons.mute) && (this.elements.buttons.mute.pressed = this.muted || this.volume === 0));
964
+ },
965
+ // Update seek value and lower fill
966
+ setRange(e, t = 0) {
967
+ r.element(e) && (e.value = t, d.updateRangeFill.call(this, e));
968
+ },
969
+ // Update <progress> elements
970
+ updateProgress(e) {
971
+ if (!this.supported.ui || !r.event(e))
972
+ return;
973
+ let t = 0;
974
+ const i = (n, s) => {
975
+ const a = r.number(s) ? s : 0, l = r.element(n) ? n : this.elements.display.buffer;
976
+ if (r.element(l)) {
977
+ l.value = a;
978
+ const o = l.getElementsByTagName("span")[0];
979
+ r.element(o) && (o.childNodes[0].nodeValue = a);
980
+ }
981
+ };
982
+ if (e)
983
+ switch (e.type) {
984
+ // Video playing
985
+ case "timeupdate":
986
+ case "seeking":
987
+ case "seeked":
988
+ t = si(this.currentTime, this.duration), e.type === "timeupdate" && d.setRange.call(this, this.elements.inputs.seek, t);
989
+ break;
990
+ // Check buffer status
991
+ case "playing":
992
+ case "progress":
993
+ i(this.elements.display.buffer, this.buffered * 100);
994
+ break;
995
+ }
996
+ },
997
+ // Webkit polyfill for lower fill range
998
+ updateRangeFill(e) {
999
+ const t = r.event(e) ? e.target : e;
1000
+ if (!(!r.element(t) || t.getAttribute("type") !== "range")) {
1001
+ if (Y(t, this.config.selectors.inputs.seek)) {
1002
+ t.setAttribute("aria-valuenow", this.currentTime);
1003
+ const i = d.formatTime(this.currentTime), n = d.formatTime(this.duration), s = O.get("seekLabel", this.config);
1004
+ t.setAttribute(
1005
+ "aria-valuetext",
1006
+ s.replace("{currentTime}", i).replace("{duration}", n)
1007
+ );
1008
+ } else if (Y(t, this.config.selectors.inputs.volume)) {
1009
+ const i = t.value * 100;
1010
+ t.setAttribute("aria-valuenow", i), t.setAttribute("aria-valuetext", `${i.toFixed(1)}%`);
1011
+ } else
1012
+ t.setAttribute("aria-valuenow", t.value);
1013
+ !_.isWebKit && !_.isIPadOS || t.style.setProperty("--value", `${t.value / t.max * 100}%`);
1014
+ }
1015
+ },
1016
+ // Update hover tooltip for seeking
1017
+ updateSeekTooltip(e) {
1018
+ var c, u;
1019
+ if (!this.config.tooltips.seek || !r.element(this.elements.inputs.seek) || !r.element(this.elements.display.seekTooltip) || this.duration === 0)
1020
+ return;
1021
+ const t = this.elements.display.seekTooltip, i = `${this.config.classNames.tooltip}--visible`, n = (f) => E(t, i, f);
1022
+ if (this.touch) {
1023
+ n(!1);
1024
+ return;
1025
+ }
1026
+ let s = 0;
1027
+ const a = this.elements.progress.getBoundingClientRect();
1028
+ if (r.event(e)) {
1029
+ const f = e.pageX - e.clientX;
1030
+ s = 100 / a.width * (e.pageX - a.left - f);
1031
+ } else if (he(t, i))
1032
+ s = Number.parseFloat(t.style.left, 10);
1033
+ else
1034
+ return;
1035
+ s < 0 ? s = 0 : s > 100 && (s = 100);
1036
+ const l = this.duration / 100 * s;
1037
+ t.textContent = d.formatTime(l);
1038
+ const o = (u = (c = this.config.markers) == null ? void 0 : c.points) == null ? void 0 : u.find(({ time: f }) => f === Math.round(l));
1039
+ o && t.insertAdjacentHTML("afterbegin", `${o.label}<br>`), t.style.left = `${s}%`, r.event(e) && ["mouseenter", "mouseleave"].includes(e.type) && n(e.type === "mouseenter");
1040
+ },
1041
+ // Handle time change event
1042
+ timeUpdate(e) {
1043
+ const t = !r.element(this.elements.display.duration) && this.config.invertTime;
1044
+ d.updateTimeDisplay.call(
1045
+ this,
1046
+ this.elements.display.currentTime,
1047
+ t ? this.duration - this.currentTime : this.currentTime,
1048
+ t
1049
+ ), !(e && e.type === "timeupdate" && this.media.seeking) && d.updateProgress.call(this, e);
1050
+ },
1051
+ // Show the duration on metadataloaded or durationchange events
1052
+ durationUpdate() {
1053
+ if (!this.supported.ui || !this.config.invertTime && this.currentTime)
1054
+ return;
1055
+ if (this.duration >= 2 ** 32) {
1056
+ K(this.elements.display.currentTime, !0), K(this.elements.progress, !0);
1057
+ return;
1058
+ }
1059
+ r.element(this.elements.inputs.seek) && this.elements.inputs.seek.setAttribute("aria-valuemax", this.duration);
1060
+ const e = r.element(this.elements.display.duration);
1061
+ !e && this.config.displayDuration && this.paused && d.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration), e && d.updateTimeDisplay.call(this, this.elements.display.duration, this.duration), this.config.markers.enabled && d.setMarkers.call(this), d.updateSeekTooltip.call(this);
1062
+ },
1063
+ // Hide/show a tab
1064
+ toggleMenuButton(e, t) {
1065
+ K(this.elements.settings.buttons[e], !t);
1066
+ },
1067
+ // Update the selected setting
1068
+ updateSetting(e, t, i) {
1069
+ const n = this.elements.settings.panels[e];
1070
+ let s = null, a = t;
1071
+ if (e === "captions")
1072
+ s = this.currentTrack;
1073
+ else {
1074
+ if (s = r.empty(i) ? this[e] : i, r.empty(s) && (s = this.config[e].default), !r.empty(this.options[e]) && !this.options[e].includes(s)) {
1075
+ this.debug.warn(`Unsupported value of '${s}' for ${e}`);
1076
+ return;
1077
+ }
1078
+ if (!this.config[e].options.includes(s)) {
1079
+ this.debug.warn(`Disabled value of '${s}' for ${e}`);
1080
+ return;
1081
+ }
1082
+ }
1083
+ if (r.element(a) || (a = n && n.querySelector('[role="menu"]')), !r.element(a))
1084
+ return;
1085
+ const l = this.elements.settings.buttons[e].querySelector(`.${this.config.classNames.menu.value}`);
1086
+ l.innerHTML = d.getLabel.call(this, e, s);
1087
+ const o = a && a.querySelector(`[value="${s}"]`);
1088
+ r.element(o) && (o.checked = !0);
1089
+ },
1090
+ // Translate a value into a nice label
1091
+ getLabel(e, t) {
1092
+ switch (e) {
1093
+ case "speed":
1094
+ return t === 1 ? O.get("normal", this.config) : `${t}&times;`;
1095
+ case "quality":
1096
+ if (r.number(t)) {
1097
+ const i = O.get(`qualityLabel.${t}`, this.config);
1098
+ return i.length ? i : `${t}p`;
1099
+ }
1100
+ return lt(t);
1101
+ case "captions":
1102
+ return C.getLabel.call(this);
1103
+ default:
1104
+ return null;
1105
+ }
1106
+ },
1107
+ // Set the quality menu
1108
+ setQualityMenu(e) {
1109
+ if (!r.element(this.elements.settings.panels.quality))
1110
+ return;
1111
+ const t = "quality", i = this.elements.settings.panels.quality.querySelector('[role="menu"]');
1112
+ r.array(e) && (this.options.quality = Ce(e).filter((a) => this.config.quality.options.includes(a)));
1113
+ const n = !r.empty(this.options.quality) && this.options.quality.length > 1;
1114
+ if (d.toggleMenuButton.call(this, t, n), ae(i), d.checkMenu.call(this), !n)
1115
+ return;
1116
+ const s = (a) => {
1117
+ const l = O.get(`qualityBadge.${a}`, this.config);
1118
+ return l.length ? d.createBadge.call(this, l) : null;
1119
+ };
1120
+ this.options.quality.sort((a, l) => {
1121
+ const o = this.config.quality.options;
1122
+ return o.indexOf(a) > o.indexOf(l) ? 1 : -1;
1123
+ }).forEach((a) => {
1124
+ d.createMenuItem.call(this, {
1125
+ value: a,
1126
+ list: i,
1127
+ type: t,
1128
+ title: d.getLabel.call(this, "quality", a),
1129
+ badge: s(a)
1130
+ });
1131
+ }), d.updateSetting.call(this, t, i);
1132
+ },
1133
+ // Set the looping options
1134
+ /* setLoopMenu() {
1135
+ // Menu required
1136
+ if (!is.element(this.elements.settings.panels.loop)) {
1137
+ return;
1138
+ }
1139
+
1140
+ const options = ['start', 'end', 'all', 'reset'];
1141
+ const list = this.elements.settings.panels.loop.querySelector('[role="menu"]');
1142
+
1143
+ // Show the pane and tab
1144
+ toggleHidden(this.elements.settings.buttons.loop, false);
1145
+ toggleHidden(this.elements.settings.panels.loop, false);
1146
+
1147
+ // Toggle the pane and tab
1148
+ const toggle = !is.empty(this.loop.options);
1149
+ controls.toggleMenuButton.call(this, 'loop', toggle);
1150
+
1151
+ // Empty the menu
1152
+ emptyElement(list);
1153
+
1154
+ options.forEach(option => {
1155
+ const item = createElement('li');
1156
+
1157
+ const button = createElement(
1158
+ 'button',
1159
+ extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {
1160
+ type: 'button',
1161
+ class: this.config.classNames.control,
1162
+ 'data-plyr-loop-action': option,
1163
+ }),
1164
+ i18n.get(option, this.config)
1165
+ );
1166
+
1167
+ if (['start', 'end'].includes(option)) {
1168
+ const badge = controls.createBadge.call(this, '00:00');
1169
+ button.appendChild(badge);
1170
+ }
1171
+
1172
+ item.appendChild(button);
1173
+ list.appendChild(item);
1174
+ });
1175
+ }, */
1176
+ // Get current selected caption language
1177
+ // TODO: rework this to user the getter in the API?
1178
+ // Set a list of available captions languages
1179
+ setCaptionsMenu() {
1180
+ if (!r.element(this.elements.settings.panels.captions))
1181
+ return;
1182
+ const e = "captions", t = this.elements.settings.panels.captions.querySelector('[role="menu"]'), i = C.getTracks.call(this), n = !!i.length;
1183
+ if (d.toggleMenuButton.call(this, e, n), ae(t), d.checkMenu.call(this), !n)
1184
+ return;
1185
+ const s = i.map((a, l) => ({
1186
+ value: l,
1187
+ checked: this.captions.toggled && this.currentTrack === l,
1188
+ title: C.getLabel.call(this, a),
1189
+ badge: a.language && d.createBadge.call(this, a.language.toUpperCase()),
1190
+ list: t,
1191
+ type: "language"
1192
+ }));
1193
+ s.unshift({
1194
+ value: -1,
1195
+ checked: !this.captions.toggled,
1196
+ title: O.get("disabled", this.config),
1197
+ list: t,
1198
+ type: "language"
1199
+ }), s.forEach(d.createMenuItem.bind(this)), d.updateSetting.call(this, e, t);
1200
+ },
1201
+ // Set a list of available captions languages
1202
+ setSpeedMenu() {
1203
+ if (!r.element(this.elements.settings.panels.speed))
1204
+ return;
1205
+ const e = "speed", t = this.elements.settings.panels.speed.querySelector('[role="menu"]');
1206
+ this.options.speed = this.options.speed.filter((n) => n >= this.minimumSpeed && n <= this.maximumSpeed);
1207
+ const i = !r.empty(this.options.speed) && this.options.speed.length > 1;
1208
+ d.toggleMenuButton.call(this, e, i), ae(t), d.checkMenu.call(this), i && (this.options.speed.forEach((n) => {
1209
+ d.createMenuItem.call(this, {
1210
+ value: n,
1211
+ list: t,
1212
+ type: e,
1213
+ title: d.getLabel.call(this, "speed", n)
1214
+ });
1215
+ }), d.updateSetting.call(this, e, t));
1216
+ },
1217
+ // Check if we need to hide/show the settings menu
1218
+ checkMenu() {
1219
+ const { buttons: e } = this.elements.settings, t = !r.empty(e) && Object.values(e).some((i) => !i.hidden);
1220
+ K(this.elements.settings.menu, !t);
1221
+ },
1222
+ // Focus the first menu item in a given (or visible) menu
1223
+ focusFirstMenuItem(e, t = !1) {
1224
+ if (this.elements.settings.popup.hidden)
1225
+ return;
1226
+ let i = e;
1227
+ r.element(i) || (i = Object.values(this.elements.settings.panels).find((s) => !s.hidden));
1228
+ const n = i.querySelector('[role^="menuitem"]');
1229
+ be.call(this, n, t);
1230
+ },
1231
+ // Show/hide menu
1232
+ toggleMenu(e) {
1233
+ const { popup: t } = this.elements.settings, i = this.elements.buttons.settings;
1234
+ if (!r.element(t) || !r.element(i))
1235
+ return;
1236
+ const { hidden: n } = t;
1237
+ let s = n;
1238
+ if (r.boolean(e))
1239
+ s = e;
1240
+ else if (r.keyboardEvent(e) && e.key === "Escape")
1241
+ s = !1;
1242
+ else if (r.event(e)) {
1243
+ const a = r.function(e.composedPath) ? e.composedPath()[0] : e.target, l = t.contains(a);
1244
+ if (l || !l && e.target !== i && s)
1245
+ return;
1246
+ }
1247
+ i.setAttribute("aria-expanded", s), K(t, !s), E(this.elements.container, this.config.classNames.menu.open, s), s && r.keyboardEvent(e) ? d.focusFirstMenuItem.call(this, null, !0) : !s && !n && be.call(this, i, r.keyboardEvent(e));
1248
+ },
1249
+ // Get the natural size of a menu panel
1250
+ getMenuSize(e) {
1251
+ const t = e.cloneNode(!0);
1252
+ t.style.position = "absolute", t.style.opacity = 0, t.removeAttribute("hidden"), e.parentNode.appendChild(t);
1253
+ const i = t.scrollWidth, n = t.scrollHeight;
1254
+ return U(t), {
1255
+ width: i,
1256
+ height: n
1257
+ };
1258
+ },
1259
+ // Show a panel in the menu
1260
+ showMenuPanel(e = "", t = !1) {
1261
+ const i = this.elements.container.querySelector(`#plyr-settings-${this.id}-${e}`);
1262
+ if (!r.element(i))
1263
+ return;
1264
+ const n = i.parentNode, s = Array.from(n.children).find((a) => !a.hidden);
1265
+ if ($.transitions && !$.reducedMotion) {
1266
+ n.style.width = `${s.scrollWidth}px`, n.style.height = `${s.scrollHeight}px`;
1267
+ const a = d.getMenuSize.call(this, i), l = (o) => {
1268
+ o.target !== n || !["width", "height"].includes(o.propertyName) || (n.style.width = "", n.style.height = "", fe.call(this, n, ke, l));
1269
+ };
1270
+ T.call(this, n, ke, l), n.style.width = `${a.width}px`, n.style.height = `${a.height}px`;
1271
+ }
1272
+ K(s, !0), K(i, !1), d.focusFirstMenuItem.call(this, i, t);
1273
+ },
1274
+ // Set the download URL
1275
+ setDownloadUrl() {
1276
+ const e = this.elements.buttons.download;
1277
+ r.element(e) && e.setAttribute("href", this.download);
1278
+ },
1279
+ // Build the default HTML
1280
+ create(e) {
1281
+ const {
1282
+ bindMenuItemShortcuts: t,
1283
+ createButton: i,
1284
+ createProgress: n,
1285
+ createRange: s,
1286
+ createTime: a,
1287
+ setQualityMenu: l,
1288
+ setSpeedMenu: o,
1289
+ showMenuPanel: c
1290
+ } = d;
1291
+ this.elements.controls = null, r.array(this.config.controls) && this.config.controls.includes("play-large") && this.elements.container.appendChild(i.call(this, "play-large"));
1292
+ const u = b("div", V(this.config.selectors.controls.wrapper));
1293
+ this.elements.controls = u;
1294
+ const f = { class: "plyr__controls__item" };
1295
+ return Ce(r.array(this.config.controls) ? this.config.controls : []).forEach((w) => {
1296
+ if (w === "restart" && u.appendChild(i.call(this, "restart", f)), w === "rewind" && u.appendChild(i.call(this, "rewind", f)), w === "play" && u.appendChild(i.call(this, "play", f)), w === "fast-forward" && u.appendChild(i.call(this, "fast-forward", f)), w === "progress") {
1297
+ const h = b("div", {
1298
+ class: `${f.class} plyr__progress__container`
1299
+ }), g = b("div", V(this.config.selectors.progress));
1300
+ if (g.appendChild(
1301
+ s.call(this, "seek", {
1302
+ id: `plyr-seek-${e.id}`
1303
+ })
1304
+ ), g.appendChild(n.call(this, "buffer")), this.config.tooltips.seek) {
1305
+ const v = b(
1306
+ "span",
1307
+ {
1308
+ class: this.config.classNames.tooltip
1309
+ },
1310
+ "00:00"
1311
+ );
1312
+ g.appendChild(v), this.elements.display.seekTooltip = v;
1313
+ }
1314
+ this.elements.progress = g, h.appendChild(this.elements.progress), u.appendChild(h);
1315
+ }
1316
+ if (w === "current-time" && u.appendChild(a.call(this, "currentTime", f)), w === "duration" && u.appendChild(a.call(this, "duration", f)), w === "mute" || w === "volume") {
1317
+ let { volume: h } = this.elements;
1318
+ if ((!r.element(h) || !u.contains(h)) && (h = b(
1319
+ "div",
1320
+ L({}, f, {
1321
+ class: `${f.class} plyr__volume`.trim()
1322
+ })
1323
+ ), this.elements.volume = h, u.appendChild(h)), w === "mute" && h.appendChild(i.call(this, "mute")), w === "volume" && !_.isIos && !_.isIPadOS) {
1324
+ const g = {
1325
+ max: 1,
1326
+ step: 0.05,
1327
+ value: this.config.volume
1328
+ };
1329
+ h.appendChild(
1330
+ s.call(
1331
+ this,
1332
+ "volume",
1333
+ L(g, {
1334
+ id: `plyr-volume-${e.id}`
1335
+ })
1336
+ )
1337
+ );
1338
+ }
1339
+ }
1340
+ if (w === "captions" && u.appendChild(i.call(this, "captions", f)), w === "settings" && !r.empty(this.config.settings)) {
1341
+ const h = b(
1342
+ "div",
1343
+ L({}, f, {
1344
+ class: `${f.class} plyr__menu`.trim(),
1345
+ hidden: ""
1346
+ })
1347
+ );
1348
+ h.appendChild(
1349
+ i.call(this, "settings", {
1350
+ "aria-haspopup": !0,
1351
+ "aria-controls": `plyr-settings-${e.id}`,
1352
+ "aria-expanded": !1
1353
+ })
1354
+ );
1355
+ const g = b("div", {
1356
+ class: "plyr__menu__container",
1357
+ id: `plyr-settings-${e.id}`,
1358
+ hidden: ""
1359
+ }), v = b("div"), A = b("div", {
1360
+ id: `plyr-settings-${e.id}-home`
1361
+ }), x = b("div", {
1362
+ role: "menu"
1363
+ });
1364
+ A.appendChild(x), v.appendChild(A), this.elements.settings.panels.home = A, this.config.settings.forEach((P) => {
1365
+ const p = b(
1366
+ "button",
1367
+ L(V(this.config.selectors.buttons.settings), {
1368
+ type: "button",
1369
+ class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,
1370
+ role: "menuitem",
1371
+ "aria-haspopup": !0,
1372
+ hidden: ""
1373
+ })
1374
+ );
1375
+ t.call(this, p, P), T.call(this, p, "click", () => {
1376
+ c.call(this, P, !1);
1377
+ });
1378
+ const k = b("span", null, O.get(P, this.config)), M = b("span", {
1379
+ class: this.config.classNames.menu.value
1380
+ });
1381
+ M.innerHTML = e[P], k.appendChild(M), p.appendChild(k), x.appendChild(p);
1382
+ const j = b("div", {
1383
+ id: `plyr-settings-${e.id}-${P}`,
1384
+ hidden: ""
1385
+ }), R = b("button", {
1386
+ type: "button",
1387
+ class: `${this.config.classNames.control} ${this.config.classNames.control}--back`
1388
+ });
1389
+ R.appendChild(
1390
+ b(
1391
+ "span",
1392
+ {
1393
+ "aria-hidden": !0
1394
+ },
1395
+ O.get(P, this.config)
1396
+ )
1397
+ ), R.appendChild(
1398
+ b(
1399
+ "span",
1400
+ {
1401
+ class: this.config.classNames.hidden
1402
+ },
1403
+ O.get("menuBack", this.config)
1404
+ )
1405
+ ), T.call(
1406
+ this,
1407
+ j,
1408
+ "keydown",
1409
+ (H) => {
1410
+ H.key === "ArrowLeft" && (H.preventDefault(), H.stopPropagation(), c.call(this, "home", !0));
1411
+ },
1412
+ !1
1413
+ ), T.call(this, R, "click", () => {
1414
+ c.call(this, "home", !1);
1415
+ }), j.appendChild(R), j.appendChild(
1416
+ b("div", {
1417
+ role: "menu"
1418
+ })
1419
+ ), v.appendChild(j), this.elements.settings.buttons[P] = p, this.elements.settings.panels[P] = j;
1420
+ }), g.appendChild(v), h.appendChild(g), u.appendChild(h), this.elements.settings.popup = g, this.elements.settings.menu = h;
1421
+ }
1422
+ if (w === "pip" && $.pip && u.appendChild(i.call(this, "pip", f)), w === "airplay" && $.airplay && u.appendChild(i.call(this, "airplay", f)), w === "download") {
1423
+ const h = L({}, f, {
1424
+ element: "a",
1425
+ href: this.download,
1426
+ target: "_blank"
1427
+ });
1428
+ this.isHTML5 && (h.download = "");
1429
+ const { download: g } = this.config.urls;
1430
+ !r.url(g) && this.isEmbed && L(h, {
1431
+ icon: `logo-${this.provider}`,
1432
+ label: this.provider
1433
+ }), u.appendChild(i.call(this, "download", h));
1434
+ }
1435
+ w === "fullscreen" && u.appendChild(i.call(this, "fullscreen", f));
1436
+ }), this.isHTML5 && l.call(this, z.getQualityOptions.call(this)), o.call(this), u;
1437
+ },
1438
+ // Insert controls
1439
+ inject() {
1440
+ if (this.config.loadSprite) {
1441
+ const l = d.getIconUrl.call(this);
1442
+ l.cors && ot(l.url, "sprite-plyr");
1443
+ }
1444
+ this.id = Math.floor(Math.random() * 1e4);
1445
+ let e = null;
1446
+ this.elements.controls = null;
1447
+ const t = {
1448
+ id: this.id,
1449
+ seektime: this.config.seekTime,
1450
+ title: this.config.title
1451
+ };
1452
+ let i = !0;
1453
+ r.function(this.config.controls) && (this.config.controls = this.config.controls.call(this, t)), this.config.controls || (this.config.controls = []), r.element(this.config.controls) || r.string(this.config.controls) ? e = this.config.controls : (e = d.create.call(this, {
1454
+ id: this.id,
1455
+ seektime: this.config.seekTime,
1456
+ speed: this.speed,
1457
+ quality: this.quality,
1458
+ captions: C.getLabel.call(this)
1459
+ // TODO: Looping
1460
+ // loop: 'None',
1461
+ }), i = !1);
1462
+ const n = (l) => {
1463
+ let o = l;
1464
+ return Object.entries(t).forEach(([c, u]) => {
1465
+ o = G(o, `{${c}}`, u);
1466
+ }), o;
1467
+ };
1468
+ i && r.string(this.config.controls) && (e = n(e));
1469
+ let s;
1470
+ r.string(this.config.selectors.controls.container) && (s = document.querySelector(this.config.selectors.controls.container)), r.element(s) || (s = this.elements.container);
1471
+ const a = r.element(e) ? "insertAdjacentElement" : "insertAdjacentHTML";
1472
+ if (s[a]("afterbegin", e), r.element(this.elements.controls) || d.findElements.call(this), !r.empty(this.elements.buttons)) {
1473
+ const l = (o) => {
1474
+ const c = this.config.classNames.controlPressed;
1475
+ o.setAttribute("aria-pressed", "false"), Object.defineProperty(o, "pressed", {
1476
+ configurable: !0,
1477
+ enumerable: !0,
1478
+ get() {
1479
+ return he(o, c);
1480
+ },
1481
+ set(u = !1) {
1482
+ E(o, c, u), o.setAttribute("aria-pressed", u ? "true" : "false");
1483
+ }
1484
+ });
1485
+ };
1486
+ Object.values(this.elements.buttons).filter(Boolean).forEach((o) => {
1487
+ r.array(o) || r.nodeList(o) ? Array.from(o).filter(Boolean).forEach(l) : l(o);
1488
+ });
1489
+ }
1490
+ if (_.isEdge && et(s), this.config.tooltips.controls) {
1491
+ const { classNames: l, selectors: o } = this.config, c = `${o.controls.wrapper} ${o.labels} .${l.hidden}`, u = Z.call(this, c);
1492
+ Array.from(u).forEach((f) => {
1493
+ E(f, this.config.classNames.hidden, !1), E(f, this.config.classNames.tooltip, !0);
1494
+ });
1495
+ }
1496
+ },
1497
+ // Set media metadata
1498
+ setMediaMetadata() {
1499
+ try {
1500
+ "mediaSession" in navigator && (navigator.mediaSession.metadata = new window.MediaMetadata({
1501
+ title: this.config.mediaMetadata.title,
1502
+ artist: this.config.mediaMetadata.artist,
1503
+ album: this.config.mediaMetadata.album,
1504
+ artwork: this.config.mediaMetadata.artwork
1505
+ }));
1506
+ } catch {
1507
+ }
1508
+ },
1509
+ // Add markers
1510
+ setMarkers() {
1511
+ var l, o;
1512
+ if (!this.duration || this.elements.markers) return;
1513
+ const e = (o = (l = this.config.markers) == null ? void 0 : l.points) == null ? void 0 : o.filter(({ time: c }) => c > 0 && c < this.duration);
1514
+ if (!(e != null && e.length)) return;
1515
+ const t = document.createDocumentFragment(), i = document.createDocumentFragment();
1516
+ let n = null;
1517
+ const s = `${this.config.classNames.tooltip}--visible`, a = (c) => E(n, s, c);
1518
+ e.forEach((c) => {
1519
+ const u = b(
1520
+ "span",
1521
+ {
1522
+ class: this.config.classNames.marker
1523
+ },
1524
+ ""
1525
+ ), f = `${c.time / this.duration * 100}%`;
1526
+ n && (u.addEventListener("mouseenter", () => {
1527
+ c.label || (n.style.left = f, n.innerHTML = c.label, a(!0));
1528
+ }), u.addEventListener("mouseleave", () => {
1529
+ a(!1);
1530
+ })), u.addEventListener("click", () => {
1531
+ this.currentTime = c.time;
1532
+ }), u.style.left = f, i.appendChild(u);
1533
+ }), t.appendChild(i), this.config.tooltips.seek || (n = b(
1534
+ "span",
1535
+ {
1536
+ class: this.config.classNames.tooltip
1537
+ },
1538
+ ""
1539
+ ), t.appendChild(n)), this.elements.markers = {
1540
+ points: i,
1541
+ tip: n
1542
+ }, this.elements.progress.appendChild(t);
1543
+ }
1544
+ };
1545
+ function ut(e, t = !0) {
1546
+ let i = e;
1547
+ if (t) {
1548
+ const n = document.createElement("a");
1549
+ n.href = i, i = n.href;
1550
+ }
1551
+ try {
1552
+ return new URL(i);
1553
+ } catch {
1554
+ return null;
1555
+ }
1556
+ }
1557
+ function ht(e) {
1558
+ const t = new URLSearchParams();
1559
+ return r.object(e) && Object.entries(e).forEach(([i, n]) => {
1560
+ t.set(i, n);
1561
+ }), t;
1562
+ }
1563
+ const C = {
1564
+ // Setup captions
1565
+ setup() {
1566
+ if (!this.supported.ui)
1567
+ return;
1568
+ if (!this.isVideo || this.isYouTube || this.isHTML5 && !$.textTracks) {
1569
+ r.array(this.config.controls) && this.config.controls.includes("settings") && this.config.settings.includes("captions") && d.setCaptionsMenu.call(this);
1570
+ return;
1571
+ }
1572
+ if (r.element(this.elements.captions) || (this.elements.captions = b("div", V(this.config.selectors.captions)), this.elements.captions.setAttribute("dir", "auto"), Wt(this.elements.captions, this.elements.wrapper)), _.isIE && window.URL) {
1573
+ const s = this.media.querySelectorAll("track");
1574
+ Array.from(s).forEach((a) => {
1575
+ const l = a.getAttribute("src"), o = ut(l);
1576
+ o !== null && o.hostname !== window.location.href.hostname && ["http:", "https:"].includes(o.protocol) && ne(l, "blob").then((c) => {
1577
+ a.setAttribute("src", window.URL.createObjectURL(c));
1578
+ }).catch(() => {
1579
+ U(a);
1580
+ });
1581
+ });
1582
+ }
1583
+ const e = navigator.languages || [navigator.language || navigator.userLanguage || "en"], t = Ce(e.map((s) => s.split("-")[0]));
1584
+ let i = (this.storage.get("language") || this.captions.language || this.config.captions.language || "auto").toLowerCase();
1585
+ i === "auto" && ([i] = t);
1586
+ let n = this.storage.get("captions") || this.captions.active;
1587
+ if (r.boolean(n) || ({ active: n } = this.config.captions), Object.assign(this.captions, {
1588
+ toggled: !1,
1589
+ active: n,
1590
+ language: i,
1591
+ languages: t
1592
+ }), this.isHTML5) {
1593
+ const s = this.config.captions.update ? "addtrack removetrack" : "removetrack";
1594
+ T.call(this, this.media.textTracks, s, C.update.bind(this));
1595
+ }
1596
+ setTimeout(C.update.bind(this), 0);
1597
+ },
1598
+ // Update available language options in settings based on tracks
1599
+ update() {
1600
+ const e = C.getTracks.call(this, !0), { active: t, language: i, meta: n, currentTrackNode: s } = this.captions, a = !!e.find((l) => l.language === i);
1601
+ this.isHTML5 && this.isVideo && e.filter((l) => !n.get(l)).forEach((l) => {
1602
+ this.debug.log("Track added", l), n.set(l, {
1603
+ default: l.mode === "showing"
1604
+ }), l.mode === "showing" && (l.mode = "hidden"), T.call(this, l, "cuechange", () => C.updateCues.call(this));
1605
+ }), (a && this.language !== i || !e.includes(s)) && (C.setLanguage.call(this, i), C.toggle.call(this, t && a)), this.elements && E(this.elements.container, this.config.classNames.captions.enabled, !r.empty(e)), r.array(this.config.controls) && this.config.controls.includes("settings") && this.config.settings.includes("captions") && d.setCaptionsMenu.call(this);
1606
+ },
1607
+ // Toggle captions display
1608
+ // Used internally for the toggleCaptions method, with the passive option forced to false
1609
+ toggle(e, t = !0) {
1610
+ if (!this.supported.ui)
1611
+ return;
1612
+ const { toggled: i } = this.captions, n = this.config.classNames.captions.active, s = r.nullOrUndefined(e) ? !i : e;
1613
+ if (s !== i) {
1614
+ if (t || (this.captions.active = s, this.storage.set({ captions: s })), !this.language && s && !t) {
1615
+ const a = C.getTracks.call(this), l = C.findTrack.call(this, [this.captions.language, ...this.captions.languages], !0);
1616
+ this.captions.language = l.language, C.set.call(this, a.indexOf(l));
1617
+ return;
1618
+ }
1619
+ this.elements.buttons.captions && (this.elements.buttons.captions.pressed = s), E(this.elements.container, n, s), this.captions.toggled = s, d.updateSetting.call(this, "captions"), y.call(this, this.media, s ? "captionsenabled" : "captionsdisabled");
1620
+ }
1621
+ setTimeout(() => {
1622
+ s && this.captions.toggled && (this.captions.currentTrackNode.mode = "hidden");
1623
+ });
1624
+ },
1625
+ // Set captions by track index
1626
+ // Used internally for the currentTrack setter with the passive option forced to false
1627
+ set(e, t = !0) {
1628
+ const i = C.getTracks.call(this);
1629
+ if (e === -1) {
1630
+ C.toggle.call(this, !1, t);
1631
+ return;
1632
+ }
1633
+ if (!r.number(e)) {
1634
+ this.debug.warn("Invalid caption argument", e);
1635
+ return;
1636
+ }
1637
+ if (!(e in i)) {
1638
+ this.debug.warn("Track not found", e);
1639
+ return;
1640
+ }
1641
+ if (this.captions.currentTrack !== e) {
1642
+ this.captions.currentTrack = e;
1643
+ const n = i[e], { language: s } = n || {};
1644
+ this.captions.currentTrackNode = n, d.updateSetting.call(this, "captions"), t || (this.captions.language = s, this.storage.set({ language: s })), this.isVimeo && this.embed.enableTextTrack(s), y.call(this, this.media, "languagechange");
1645
+ }
1646
+ C.toggle.call(this, !0, t), this.isHTML5 && this.isVideo && C.updateCues.call(this);
1647
+ },
1648
+ // Set captions by language
1649
+ // Used internally for the language setter with the passive option forced to false
1650
+ setLanguage(e, t = !0) {
1651
+ if (!r.string(e)) {
1652
+ this.debug.warn("Invalid language argument", e);
1653
+ return;
1654
+ }
1655
+ const i = e.toLowerCase();
1656
+ this.captions.language = i;
1657
+ const n = C.getTracks.call(this), s = C.findTrack.call(this, [i]);
1658
+ C.set.call(this, n.indexOf(s), t);
1659
+ },
1660
+ // Get current valid caption tracks
1661
+ // If update is false it will also ignore tracks without metadata
1662
+ // This is used to "freeze" the language options when captions.update is false
1663
+ getTracks(e = !1) {
1664
+ return Array.from((this.media || {}).textTracks || []).filter((i) => !this.isHTML5 || e || this.captions.meta.has(i)).filter((i) => ["captions", "subtitles"].includes(i.kind));
1665
+ },
1666
+ // Match tracks based on languages and get the first
1667
+ findTrack(e, t = !1) {
1668
+ const i = C.getTracks.call(this), n = (l) => Number((this.captions.meta.get(l) || {}).default), s = Array.from(i).sort((l, o) => n(o) - n(l));
1669
+ let a;
1670
+ return e.every((l) => (a = s.find((o) => o.language === l), !a)), a || (t ? s[0] : void 0);
1671
+ },
1672
+ // Get the current track
1673
+ getCurrentTrack() {
1674
+ return C.getTracks.call(this)[this.currentTrack];
1675
+ },
1676
+ // Get UI label for track
1677
+ getLabel(e) {
1678
+ let t = e;
1679
+ return !r.track(t) && $.textTracks && this.captions.toggled && (t = C.getCurrentTrack.call(this)), r.track(t) ? r.empty(t.label) ? r.empty(t.language) ? O.get("enabled", this.config) : e.language.toUpperCase() : t.label : O.get("disabled", this.config);
1680
+ },
1681
+ // Update captions using current track's active cues
1682
+ // Also optional array argument in case there isn't any track (ex: vimeo)
1683
+ updateCues(e) {
1684
+ if (!this.supported.ui)
1685
+ return;
1686
+ if (!r.element(this.elements.captions)) {
1687
+ this.debug.warn("No captions element to render to");
1688
+ return;
1689
+ }
1690
+ if (!r.nullOrUndefined(e) && !Array.isArray(e)) {
1691
+ this.debug.warn("updateCues: Invalid input", e);
1692
+ return;
1693
+ }
1694
+ let t = e;
1695
+ if (!t) {
1696
+ const s = C.getCurrentTrack.call(this);
1697
+ t = Array.from((s || {}).activeCues || []).map((a) => a.getCueAsHTML()).map(li);
1698
+ }
1699
+ const i = t.map((s) => s.trim()).join(`
1700
+ `);
1701
+ if (i !== this.elements.captions.innerHTML) {
1702
+ ae(this.elements.captions);
1703
+ const s = b("span", V(this.config.selectors.caption));
1704
+ s.innerHTML = i, this.elements.captions.appendChild(s), y.call(this, this.media, "cuechange");
1705
+ }
1706
+ }
1707
+ }, dt = {
1708
+ // Disable
1709
+ enabled: !0,
1710
+ // Custom media title
1711
+ title: "",
1712
+ // Logging to console
1713
+ debug: !1,
1714
+ // Auto play (if supported)
1715
+ autoplay: !1,
1716
+ // Only allow one media playing at once (vimeo only)
1717
+ autopause: !0,
1718
+ // Allow inline playback on iOS
1719
+ playsinline: !0,
1720
+ // Default time to skip when rewind/fast forward
1721
+ seekTime: 10,
1722
+ // Default volume
1723
+ volume: 1,
1724
+ muted: !1,
1725
+ // Pass a custom duration
1726
+ duration: null,
1727
+ // Display the media duration on load in the current time position
1728
+ // If you have opted to display both duration and currentTime, this is ignored
1729
+ displayDuration: !0,
1730
+ // Invert the current time to be a countdown
1731
+ invertTime: !0,
1732
+ // Clicking the currentTime inverts it's value to show time left rather than elapsed
1733
+ toggleInvert: !0,
1734
+ // Force an aspect ratio
1735
+ // The format must be `'w:h'` (e.g. `'16:9'`)
1736
+ ratio: null,
1737
+ // Click video container to play/pause
1738
+ clickToPlay: !0,
1739
+ // Auto hide the controls
1740
+ hideControls: !0,
1741
+ // Reset to start when playback ended
1742
+ resetOnEnd: !1,
1743
+ // Disable the standard context menu
1744
+ disableContextMenu: !0,
1745
+ // Sprite (for icons)
1746
+ loadSprite: !0,
1747
+ iconPrefix: "plyr",
1748
+ iconUrl: "https://cdn.plyr.io/3.8.3/plyr.svg",
1749
+ // Blank video (used to prevent errors on source change)
1750
+ blankVideo: "https://cdn.plyr.io/static/blank.mp4",
1751
+ // Quality default
1752
+ quality: {
1753
+ default: 576,
1754
+ // The options to display in the UI, if available for the source media
1755
+ options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],
1756
+ forced: !1,
1757
+ onChange: null
1758
+ },
1759
+ // Set loops
1760
+ loop: {
1761
+ active: !1
1762
+ // start: null,
1763
+ // end: null,
1764
+ },
1765
+ // Speed default and options to display
1766
+ speed: {
1767
+ selected: 1,
1768
+ // The options to display in the UI, if available for the source media (e.g. Vimeo and YouTube only support 0.5x-4x)
1769
+ options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4]
1770
+ },
1771
+ // Keyboard shortcut settings
1772
+ keyboard: {
1773
+ focused: !0,
1774
+ global: !1
1775
+ },
1776
+ // Display tooltips
1777
+ tooltips: {
1778
+ controls: !1,
1779
+ seek: !0
1780
+ },
1781
+ // Captions settings
1782
+ captions: {
1783
+ active: !1,
1784
+ language: "auto",
1785
+ // Listen to new tracks added after Plyr is initialized.
1786
+ // This is needed for streaming captions, but may result in unselectable options
1787
+ update: !1
1788
+ },
1789
+ // Fullscreen settings
1790
+ fullscreen: {
1791
+ enabled: !0,
1792
+ // Allow fullscreen?
1793
+ fallback: !0,
1794
+ // Fallback using full viewport/window
1795
+ iosNative: !1
1796
+ // Use the native fullscreen in iOS (disables custom controls)
1797
+ // Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode
1798
+ // Non-ancestors of the player element will be ignored
1799
+ // container: null, // defaults to the player element
1800
+ },
1801
+ // Local storage
1802
+ storage: {
1803
+ enabled: !0,
1804
+ key: "plyr"
1805
+ },
1806
+ // Default controls
1807
+ controls: [
1808
+ "play-large",
1809
+ // 'restart',
1810
+ // 'rewind',
1811
+ "play",
1812
+ // 'fast-forward',
1813
+ "progress",
1814
+ "current-time",
1815
+ // 'duration',
1816
+ "mute",
1817
+ "volume",
1818
+ "captions",
1819
+ "settings",
1820
+ "pip",
1821
+ "airplay",
1822
+ // 'download',
1823
+ "fullscreen"
1824
+ ],
1825
+ settings: ["captions", "quality", "speed"],
1826
+ // Localisation
1827
+ i18n: {
1828
+ restart: "Restart",
1829
+ rewind: "Rewind {seektime}s",
1830
+ play: "Play",
1831
+ pause: "Pause",
1832
+ fastForward: "Forward {seektime}s",
1833
+ seek: "Seek",
1834
+ seekLabel: "{currentTime} of {duration}",
1835
+ played: "Played",
1836
+ buffered: "Buffered",
1837
+ currentTime: "Current time",
1838
+ duration: "Duration",
1839
+ volume: "Volume",
1840
+ mute: "Mute",
1841
+ unmute: "Unmute",
1842
+ enableCaptions: "Enable captions",
1843
+ disableCaptions: "Disable captions",
1844
+ download: "Download",
1845
+ enterFullscreen: "Enter fullscreen",
1846
+ exitFullscreen: "Exit fullscreen",
1847
+ frameTitle: "Player for {title}",
1848
+ captions: "Captions",
1849
+ settings: "Settings",
1850
+ pip: "PIP",
1851
+ menuBack: "Go back to previous menu",
1852
+ speed: "Speed",
1853
+ normal: "Normal",
1854
+ quality: "Quality",
1855
+ loop: "Loop",
1856
+ start: "Start",
1857
+ end: "End",
1858
+ all: "All",
1859
+ reset: "Reset",
1860
+ disabled: "Disabled",
1861
+ enabled: "Enabled",
1862
+ advertisement: "Ad",
1863
+ qualityBadge: {
1864
+ 2160: "4K",
1865
+ 1440: "HD",
1866
+ 1080: "HD",
1867
+ 720: "HD",
1868
+ 576: "SD",
1869
+ 480: "SD"
1870
+ }
1871
+ },
1872
+ // URLs
1873
+ urls: {
1874
+ download: null,
1875
+ vimeo: {
1876
+ sdk: "https://player.vimeo.com/api/player.js",
1877
+ iframe: "https://player.vimeo.com/video/{0}?{1}",
1878
+ api: "https://vimeo.com/api/oembed.json?url={0}"
1879
+ },
1880
+ youtube: {
1881
+ sdk: "https://www.youtube.com/iframe_api",
1882
+ api: "https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}"
1883
+ },
1884
+ googleIMA: {
1885
+ sdk: "https://imasdk.googleapis.com/js/sdkloader/ima3.js"
1886
+ }
1887
+ },
1888
+ // Custom control listeners
1889
+ listeners: {
1890
+ seek: null,
1891
+ play: null,
1892
+ pause: null,
1893
+ restart: null,
1894
+ rewind: null,
1895
+ fastForward: null,
1896
+ mute: null,
1897
+ volume: null,
1898
+ captions: null,
1899
+ download: null,
1900
+ fullscreen: null,
1901
+ pip: null,
1902
+ airplay: null,
1903
+ speed: null,
1904
+ quality: null,
1905
+ loop: null,
1906
+ language: null
1907
+ },
1908
+ // Events to watch and bubble
1909
+ events: [
1910
+ // Events to watch on HTML5 media elements and bubble
1911
+ // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events
1912
+ "ended",
1913
+ "progress",
1914
+ "stalled",
1915
+ "playing",
1916
+ "waiting",
1917
+ "canplay",
1918
+ "canplaythrough",
1919
+ "loadstart",
1920
+ "loadeddata",
1921
+ "loadedmetadata",
1922
+ "timeupdate",
1923
+ "volumechange",
1924
+ "play",
1925
+ "pause",
1926
+ "error",
1927
+ "seeking",
1928
+ "seeked",
1929
+ "emptied",
1930
+ "ratechange",
1931
+ "cuechange",
1932
+ // Custom events
1933
+ "download",
1934
+ "enterfullscreen",
1935
+ "exitfullscreen",
1936
+ "captionsenabled",
1937
+ "captionsdisabled",
1938
+ "languagechange",
1939
+ "controlshidden",
1940
+ "controlsshown",
1941
+ "ready",
1942
+ // YouTube
1943
+ "statechange",
1944
+ // Quality
1945
+ "qualitychange",
1946
+ // Ads
1947
+ "adsloaded",
1948
+ "adscontentpause",
1949
+ "adscontentresume",
1950
+ "adstarted",
1951
+ "adsmidpoint",
1952
+ "adscomplete",
1953
+ "adsallcomplete",
1954
+ "adsimpression",
1955
+ "adsclick"
1956
+ ],
1957
+ // Selectors
1958
+ // Change these to match your template if using custom HTML
1959
+ selectors: {
1960
+ editable: "input, textarea, select, [contenteditable]",
1961
+ container: ".plyr",
1962
+ controls: {
1963
+ container: null,
1964
+ wrapper: ".plyr__controls"
1965
+ },
1966
+ labels: "[data-plyr]",
1967
+ buttons: {
1968
+ play: '[data-plyr="play"]',
1969
+ pause: '[data-plyr="pause"]',
1970
+ restart: '[data-plyr="restart"]',
1971
+ rewind: '[data-plyr="rewind"]',
1972
+ fastForward: '[data-plyr="fast-forward"]',
1973
+ mute: '[data-plyr="mute"]',
1974
+ captions: '[data-plyr="captions"]',
1975
+ download: '[data-plyr="download"]',
1976
+ fullscreen: '[data-plyr="fullscreen"]',
1977
+ pip: '[data-plyr="pip"]',
1978
+ airplay: '[data-plyr="airplay"]',
1979
+ settings: '[data-plyr="settings"]',
1980
+ loop: '[data-plyr="loop"]'
1981
+ },
1982
+ inputs: {
1983
+ seek: '[data-plyr="seek"]',
1984
+ volume: '[data-plyr="volume"]',
1985
+ speed: '[data-plyr="speed"]',
1986
+ language: '[data-plyr="language"]',
1987
+ quality: '[data-plyr="quality"]'
1988
+ },
1989
+ display: {
1990
+ currentTime: ".plyr__time--current",
1991
+ duration: ".plyr__time--duration",
1992
+ buffer: ".plyr__progress__buffer",
1993
+ loop: ".plyr__progress__loop",
1994
+ // Used later
1995
+ volume: ".plyr__volume--display"
1996
+ },
1997
+ progress: ".plyr__progress",
1998
+ captions: ".plyr__captions",
1999
+ caption: ".plyr__caption"
2000
+ },
2001
+ // Class hooks added to the player in different states
2002
+ classNames: {
2003
+ type: "plyr--{0}",
2004
+ provider: "plyr--{0}",
2005
+ video: "plyr__video-wrapper",
2006
+ embed: "plyr__video-embed",
2007
+ videoFixedRatio: "plyr__video-wrapper--fixed-ratio",
2008
+ embedContainer: "plyr__video-embed__container",
2009
+ poster: "plyr__poster",
2010
+ posterEnabled: "plyr__poster-enabled",
2011
+ ads: "plyr__ads",
2012
+ control: "plyr__control",
2013
+ controlPressed: "plyr__control--pressed",
2014
+ playing: "plyr--playing",
2015
+ paused: "plyr--paused",
2016
+ stopped: "plyr--stopped",
2017
+ loading: "plyr--loading",
2018
+ hover: "plyr--hover",
2019
+ tooltip: "plyr__tooltip",
2020
+ cues: "plyr__cues",
2021
+ marker: "plyr__progress__marker",
2022
+ hidden: "plyr__sr-only",
2023
+ hideControls: "plyr--hide-controls",
2024
+ isTouch: "plyr--is-touch",
2025
+ uiSupported: "plyr--full-ui",
2026
+ noTransition: "plyr--no-transition",
2027
+ display: {
2028
+ time: "plyr__time"
2029
+ },
2030
+ menu: {
2031
+ value: "plyr__menu__value",
2032
+ badge: "plyr__badge",
2033
+ open: "plyr--menu-open"
2034
+ },
2035
+ captions: {
2036
+ enabled: "plyr--captions-enabled",
2037
+ active: "plyr--captions-active"
2038
+ },
2039
+ fullscreen: {
2040
+ enabled: "plyr--fullscreen-enabled",
2041
+ fallback: "plyr--fullscreen-fallback"
2042
+ },
2043
+ pip: {
2044
+ supported: "plyr--pip-supported",
2045
+ active: "plyr--pip-active"
2046
+ },
2047
+ airplay: {
2048
+ supported: "plyr--airplay-supported",
2049
+ active: "plyr--airplay-active"
2050
+ },
2051
+ previewThumbnails: {
2052
+ // Tooltip thumbs
2053
+ thumbContainer: "plyr__preview-thumb",
2054
+ thumbContainerShown: "plyr__preview-thumb--is-shown",
2055
+ imageContainer: "plyr__preview-thumb__image-container",
2056
+ timeContainer: "plyr__preview-thumb__time-container",
2057
+ // Scrubbing
2058
+ scrubbingContainer: "plyr__preview-scrubbing",
2059
+ scrubbingContainerShown: "plyr__preview-scrubbing--is-shown"
2060
+ }
2061
+ },
2062
+ // Embed attributes
2063
+ attributes: {
2064
+ embed: {
2065
+ provider: "data-plyr-provider",
2066
+ id: "data-plyr-embed-id",
2067
+ hash: "data-plyr-embed-hash"
2068
+ }
2069
+ },
2070
+ // Advertisements plugin
2071
+ // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio
2072
+ ads: {
2073
+ enabled: !1,
2074
+ publisherId: "",
2075
+ tagUrl: ""
2076
+ },
2077
+ // Preview Thumbnails plugin
2078
+ previewThumbnails: {
2079
+ enabled: !1,
2080
+ src: "",
2081
+ withCredentials: !1
2082
+ },
2083
+ // Vimeo plugin
2084
+ vimeo: {
2085
+ byline: !1,
2086
+ portrait: !1,
2087
+ title: !1,
2088
+ speed: !0,
2089
+ transparent: !1,
2090
+ // Custom settings from Plyr
2091
+ customControls: !0,
2092
+ referrerPolicy: null,
2093
+ // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
2094
+ // Whether the owner of the video has a Pro or Business account
2095
+ // (which allows us to properly hide controls without CSS hacks, etc)
2096
+ premium: !1
2097
+ },
2098
+ // YouTube plugin
2099
+ youtube: {
2100
+ rel: 0,
2101
+ // No related vids
2102
+ showinfo: 0,
2103
+ // Hide info
2104
+ iv_load_policy: 3,
2105
+ // Hide annotations
2106
+ modestbranding: 1,
2107
+ // Hide logos as much as possible (they still show one in the corner when paused)
2108
+ // Custom settings from Plyr
2109
+ customControls: !0,
2110
+ noCookie: !1
2111
+ // Whether to use an alternative version of YouTube without cookies
2112
+ },
2113
+ // Media Metadata
2114
+ mediaMetadata: {
2115
+ title: "",
2116
+ artist: "",
2117
+ album: "",
2118
+ artwork: []
2119
+ },
2120
+ // Markers
2121
+ markers: {
2122
+ enabled: !1,
2123
+ points: []
2124
+ }
2125
+ }, ye = {
2126
+ active: "picture-in-picture",
2127
+ inactive: "inline"
2128
+ }, W = {
2129
+ html5: "html5",
2130
+ youtube: "youtube",
2131
+ vimeo: "vimeo"
2132
+ }, we = {
2133
+ audio: "audio",
2134
+ video: "video"
2135
+ };
2136
+ function ui(e) {
2137
+ return /^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(e) ? W.youtube : /^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(e) ? W.vimeo : null;
2138
+ }
2139
+ function ve() {
2140
+ }
2141
+ class hi {
2142
+ constructor(t = !1) {
2143
+ this.enabled = window.console && t, this.enabled && this.log("Debugging enabled");
2144
+ }
2145
+ get log() {
2146
+ return this.enabled ? Function.prototype.bind.call(console.log, console) : ve;
2147
+ }
2148
+ get warn() {
2149
+ return this.enabled ? Function.prototype.bind.call(console.warn, console) : ve;
2150
+ }
2151
+ get error() {
2152
+ return this.enabled ? Function.prototype.bind.call(console.error, console) : ve;
2153
+ }
2154
+ }
2155
+ class q {
2156
+ constructor(t) {
2157
+ m(this, "onChange", () => {
2158
+ if (!this.supported) return;
2159
+ const t = this.player.elements.buttons.fullscreen;
2160
+ r.element(t) && (t.pressed = this.active);
2161
+ const i = this.target === this.player.media ? this.target : this.player.elements.container;
2162
+ y.call(this.player, i, this.active ? "enterfullscreen" : "exitfullscreen", !0);
2163
+ });
2164
+ m(this, "toggleFallback", (t = !1) => {
2165
+ if (t ? this.scrollPosition = {
2166
+ x: window.scrollX ?? 0,
2167
+ y: window.scrollY ?? 0
2168
+ } : window.scrollTo(this.scrollPosition.x, this.scrollPosition.y), document.body.style.overflow = t ? "hidden" : "", E(this.target, this.player.config.classNames.fullscreen.fallback, t), _.isIos) {
2169
+ let i = document.head.querySelector('meta[name="viewport"]');
2170
+ const n = "viewport-fit=cover";
2171
+ i || (i = document.createElement("meta"), i.setAttribute("name", "viewport"));
2172
+ const s = r.string(i.content) && i.content.includes(n);
2173
+ t ? (this.cleanupViewport = !s, s || (i.content += `,${n}`)) : this.cleanupViewport && (i.content = i.content.split(",").filter((a) => a.trim() !== n).join(","));
2174
+ }
2175
+ this.onChange();
2176
+ });
2177
+ // Trap focus inside container
2178
+ m(this, "trapFocus", (t) => {
2179
+ if (_.isIos || _.isIPadOS || !this.active || t.key !== "Tab") return;
2180
+ const i = document.activeElement, n = Z.call(this.player, "a[href], button:not(:disabled), input:not(:disabled), [tabindex]"), [s] = n, a = n[n.length - 1];
2181
+ i === a && !t.shiftKey ? (s.focus(), t.preventDefault()) : i === s && t.shiftKey && (a.focus(), t.preventDefault());
2182
+ });
2183
+ // Update UI
2184
+ m(this, "update", () => {
2185
+ if (this.supported) {
2186
+ let t;
2187
+ this.forceFallback ? t = "Fallback (forced)" : q.nativeSupported ? t = "Native" : t = "Fallback", this.player.debug.log(`${t} fullscreen enabled`);
2188
+ } else
2189
+ this.player.debug.log("Fullscreen not supported and fallback disabled");
2190
+ E(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.supported);
2191
+ });
2192
+ // Make an element fullscreen
2193
+ m(this, "enter", () => {
2194
+ this.supported && (_.isIos && this.player.config.fullscreen.iosNative ? this.player.isVimeo ? this.player.embed.requestFullscreen() : this.target.webkitEnterFullscreen() : !q.nativeSupported || this.forceFallback ? this.toggleFallback(!0) : this.prefix ? r.empty(this.prefix) || this.target[`${this.prefix}Request${this.property}`]() : this.target.requestFullscreen({ navigationUI: "hide" }));
2195
+ });
2196
+ // Bail from fullscreen
2197
+ m(this, "exit", () => {
2198
+ if (this.supported) {
2199
+ if (_.isIos && this.player.config.fullscreen.iosNative)
2200
+ this.player.isVimeo ? this.player.embed.exitFullscreen() : this.target.webkitEnterFullscreen(), F(this.player.play());
2201
+ else if (!q.nativeSupported || this.forceFallback)
2202
+ this.toggleFallback(!1);
2203
+ else if (!this.prefix)
2204
+ (document.cancelFullScreen || document.exitFullscreen).call(document);
2205
+ else if (!r.empty(this.prefix)) {
2206
+ const t = this.prefix === "moz" ? "Cancel" : "Exit";
2207
+ document[`${this.prefix}${t}${this.property}`]();
2208
+ }
2209
+ }
2210
+ });
2211
+ // Toggle state
2212
+ m(this, "toggle", () => {
2213
+ this.active ? this.exit() : this.enter();
2214
+ });
2215
+ this.player = t, this.prefix = q.prefix, this.property = q.property, this.scrollPosition = { x: 0, y: 0 }, this.forceFallback = t.config.fullscreen.fallback === "force", this.player.elements.fullscreen = t.config.fullscreen.container && zt(this.player.elements.container, t.config.fullscreen.container), T.call(
2216
+ this.player,
2217
+ document,
2218
+ this.prefix === "ms" ? "MSFullscreenChange" : `${this.prefix}fullscreenchange`,
2219
+ () => {
2220
+ this.onChange();
2221
+ }
2222
+ ), T.call(this.player, this.player.elements.container, "dblclick", (i) => {
2223
+ r.element(this.player.elements.controls) && this.player.elements.controls.contains(i.target) || this.player.listeners.proxy(i, this.toggle, "fullscreen");
2224
+ }), T.call(this, this.player.elements.container, "keydown", (i) => this.trapFocus(i)), this.update();
2225
+ }
2226
+ // Determine if native supported
2227
+ static get nativeSupported() {
2228
+ return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled);
2229
+ }
2230
+ // If we're actually using native
2231
+ get useNative() {
2232
+ return q.nativeSupported && !this.forceFallback;
2233
+ }
2234
+ // Get the prefix for handlers
2235
+ static get prefix() {
2236
+ if (r.function(document.exitFullscreen)) return "";
2237
+ let t = "";
2238
+ return ["webkit", "moz", "ms"].some((n) => r.function(document[`${n}ExitFullscreen`]) || r.function(document[`${n}CancelFullScreen`]) ? (t = n, !0) : !1), t;
2239
+ }
2240
+ static get property() {
2241
+ return this.prefix === "moz" ? "FullScreen" : "Fullscreen";
2242
+ }
2243
+ // Determine if fullscreen is supported
2244
+ get supported() {
2245
+ return [
2246
+ // Fullscreen is enabled in config
2247
+ this.player.config.fullscreen.enabled,
2248
+ // Must be a video
2249
+ this.player.isVideo,
2250
+ // Either native is supported or fallback enabled
2251
+ q.nativeSupported || this.player.config.fullscreen.fallback,
2252
+ // YouTube has no way to trigger fullscreen, so on devices with no native support, playsinline
2253
+ // must be enabled and iosNative fullscreen must be disabled to offer the fullscreen fallback
2254
+ !this.player.isYouTube || q.nativeSupported || !_.isIos || this.player.config.playsinline && !this.player.config.fullscreen.iosNative
2255
+ ].every(Boolean);
2256
+ }
2257
+ // Get active state
2258
+ get active() {
2259
+ if (!this.supported) return !1;
2260
+ if (!q.nativeSupported || this.forceFallback)
2261
+ return he(this.target, this.player.config.classNames.fullscreen.fallback);
2262
+ const t = this.prefix ? this.target.getRootNode()[`${this.prefix}${this.property}Element`] : this.target.getRootNode().fullscreenElement;
2263
+ return t && t.shadowRoot ? t === this.target.getRootNode().host : t === this.target;
2264
+ }
2265
+ // Get target element
2266
+ get target() {
2267
+ return _.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.fullscreen ?? this.player.elements.container;
2268
+ }
2269
+ }
2270
+ function le(e, t = 1) {
2271
+ return new Promise((i, n) => {
2272
+ const s = new Image(), a = () => {
2273
+ delete s.onload, delete s.onerror, (s.naturalWidth >= t ? i : n)(s);
2274
+ };
2275
+ Object.assign(s, { onload: a, onerror: a, src: e });
2276
+ });
2277
+ }
2278
+ const S = {
2279
+ addStyleHook() {
2280
+ E(this.elements.container, this.config.selectors.container.replace(".", ""), !0), E(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);
2281
+ },
2282
+ // Toggle native HTML5 media controls
2283
+ toggleNativeControls(e = !1) {
2284
+ e && this.isHTML5 ? this.media.setAttribute("controls", "") : this.media.removeAttribute("controls");
2285
+ },
2286
+ // Setup the UI
2287
+ build() {
2288
+ if (this.listeners.media(), !this.supported.ui) {
2289
+ this.debug.warn(`Basic support only for ${this.provider} ${this.type}`), S.toggleNativeControls.call(this, !0);
2290
+ return;
2291
+ }
2292
+ r.element(this.elements.controls) || (d.inject.call(this), this.listeners.controls()), S.toggleNativeControls.call(this), this.isHTML5 && C.setup.call(this), this.volume = null, this.muted = null, this.loop = null, this.quality = null, this.speed = null, d.updateVolume.call(this), d.timeUpdate.call(this), d.durationUpdate.call(this), S.checkPlaying.call(this), E(
2293
+ this.elements.container,
2294
+ this.config.classNames.pip.supported,
2295
+ $.pip && this.isHTML5 && this.isVideo
2296
+ ), E(this.elements.container, this.config.classNames.airplay.supported, $.airplay && this.isHTML5), E(this.elements.container, this.config.classNames.isTouch, this.touch), this.ready = !0, setTimeout(() => {
2297
+ y.call(this, this.media, "ready");
2298
+ }, 0), S.setTitle.call(this), this.poster && S.setPoster.call(this, this.poster, !1).catch(() => {
2299
+ }), this.config.duration && d.durationUpdate.call(this), this.config.mediaMetadata && d.setMediaMetadata.call(this);
2300
+ },
2301
+ // Setup aria attribute for play and iframe title
2302
+ setTitle() {
2303
+ let e = O.get("play", this.config);
2304
+ if (r.string(this.config.title) && !r.empty(this.config.title) && (e += `, ${this.config.title}`), Array.from(this.elements.buttons.play || []).forEach((t) => {
2305
+ t.setAttribute("aria-label", e);
2306
+ }), this.isEmbed) {
2307
+ const t = I.call(this, "iframe");
2308
+ if (!r.element(t))
2309
+ return;
2310
+ const i = r.empty(this.config.title) ? "video" : this.config.title, n = O.get("frameTitle", this.config);
2311
+ t.setAttribute("title", n.replace("{title}", i));
2312
+ }
2313
+ },
2314
+ // Toggle poster
2315
+ togglePoster(e) {
2316
+ E(this.elements.container, this.config.classNames.posterEnabled, e);
2317
+ },
2318
+ // Set the poster image (async)
2319
+ // Used internally for the poster setter, with the passive option forced to false
2320
+ setPoster(e, t = !0) {
2321
+ return t && this.poster ? Promise.reject(new Error("Poster already set")) : (this.media.setAttribute("data-poster", e), this.elements.poster.removeAttribute("hidden"), Xt.call(this).then(() => le(e)).catch((i) => {
2322
+ throw e === this.poster && S.togglePoster.call(this, !1), i;
2323
+ }).then(() => {
2324
+ if (e !== this.poster)
2325
+ throw new Error("setPoster cancelled by later call to setPoster");
2326
+ }).then(() => (Object.assign(this.elements.poster.style, {
2327
+ backgroundImage: `url('${e}')`,
2328
+ // Reset backgroundSize as well (since it can be set to "cover" for padded thumbnails for youtube)
2329
+ backgroundSize: ""
2330
+ }), S.togglePoster.call(this, !0), e)));
2331
+ },
2332
+ // Check playing state
2333
+ checkPlaying(e) {
2334
+ E(this.elements.container, this.config.classNames.playing, this.playing), E(this.elements.container, this.config.classNames.paused, this.paused), E(this.elements.container, this.config.classNames.stopped, this.stopped), Array.from(this.elements.buttons.play || []).forEach((t) => {
2335
+ Object.assign(t, { pressed: this.playing }), t.setAttribute("aria-label", O.get(this.playing ? "pause" : "play", this.config));
2336
+ }), !(r.event(e) && e.type === "timeupdate") && S.toggleControls.call(this);
2337
+ },
2338
+ // Check if media is loading
2339
+ checkLoading(e) {
2340
+ this.loading = ["stalled", "waiting"].includes(e.type), clearTimeout(this.timers.loading), this.timers.loading = setTimeout(
2341
+ () => {
2342
+ E(this.elements.container, this.config.classNames.loading, this.loading), S.toggleControls.call(this);
2343
+ },
2344
+ this.loading ? 250 : 0
2345
+ );
2346
+ },
2347
+ // Toggle controls based on state and `force` argument
2348
+ toggleControls(e) {
2349
+ const { controls: t } = this.elements;
2350
+ if (t && this.config.hideControls) {
2351
+ const i = this.touch && this.lastSeekTime + 2e3 > Date.now();
2352
+ this.toggleControls(
2353
+ !!(e || this.loading || this.paused || t.pressed || t.hover || i)
2354
+ );
2355
+ }
2356
+ },
2357
+ // Migrate any custom properties from the media to the parent
2358
+ migrateStyles() {
2359
+ Object.values({ ...this.media.style }).filter((e) => !r.empty(e) && r.string(e) && e.startsWith("--plyr")).forEach((e) => {
2360
+ this.elements.container.style.setProperty(e, this.media.style.getPropertyValue(e)), this.media.style.removeProperty(e);
2361
+ }), r.empty(this.media.style) && this.media.removeAttribute("style");
2362
+ }
2363
+ };
2364
+ class di {
2365
+ constructor(t) {
2366
+ // Device is touch enabled
2367
+ m(this, "firstTouch", () => {
2368
+ const { player: t } = this, { elements: i } = t;
2369
+ t.touch = !0, E(i.container, t.config.classNames.isTouch, !0);
2370
+ });
2371
+ // Global window & document listeners
2372
+ m(this, "global", (t = !0) => {
2373
+ const { player: i } = this;
2374
+ i.config.keyboard.global && ee.call(i, window, "keydown keyup", this.handleKey, t, !1), ee.call(i, document.body, "click", this.toggleMenu, t), xe.call(i, document.body, "touchstart", this.firstTouch);
2375
+ });
2376
+ // Container listeners
2377
+ m(this, "container", () => {
2378
+ const { player: t } = this, { config: i, elements: n, timers: s } = t;
2379
+ !i.keyboard.global && i.keyboard.focused && T.call(t, n.container, "keydown keyup", this.handleKey, !1), T.call(
2380
+ t,
2381
+ n.container,
2382
+ "mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen",
2383
+ (o) => {
2384
+ const { controls: c } = n;
2385
+ c && o.type === "enterfullscreen" && (c.pressed = !1, c.hover = !1);
2386
+ const u = ["touchstart", "touchmove", "mousemove"].includes(o.type);
2387
+ let f = 0;
2388
+ u && (S.toggleControls.call(t, !0), f = t.touch ? 3e3 : 2e3), clearTimeout(s.controls), s.controls = setTimeout(() => S.toggleControls.call(t, !1), f);
2389
+ }
2390
+ );
2391
+ const a = () => {
2392
+ if (!t.isVimeo || t.config.vimeo.premium)
2393
+ return;
2394
+ const o = n.wrapper, { active: c } = t.fullscreen, [u, f] = Le.call(t), w = nt(`aspect-ratio: ${u} / ${f}`);
2395
+ if (!c) {
2396
+ w ? (o.style.width = null, o.style.height = null) : (o.style.maxWidth = null, o.style.margin = null);
2397
+ return;
2398
+ }
2399
+ const [h, g] = Qt(), v = h / g > u / f;
2400
+ w ? (o.style.width = v ? "auto" : "100%", o.style.height = v ? "100%" : "auto") : (o.style.maxWidth = v ? `${g / f * u}px` : null, o.style.margin = v ? "0 auto" : null);
2401
+ }, l = () => {
2402
+ clearTimeout(s.resized), s.resized = setTimeout(a, 50);
2403
+ };
2404
+ T.call(t, n.container, "enterfullscreen exitfullscreen", (o) => {
2405
+ const { target: c } = t.fullscreen;
2406
+ if (c !== n.container || !t.isEmbed && r.empty(t.config.ratio))
2407
+ return;
2408
+ a(), (o.type === "enterfullscreen" ? T : fe).call(t, window, "resize", l);
2409
+ });
2410
+ });
2411
+ // Listen for media events
2412
+ m(this, "media", () => {
2413
+ const { player: t } = this, { elements: i } = t;
2414
+ if (T.call(t, t.media, "timeupdate seeking seeked", (s) => d.timeUpdate.call(t, s)), T.call(t, t.media, "durationchange loadeddata loadedmetadata", (s) => d.durationUpdate.call(t, s)), T.call(t, t.media, "ended", () => {
2415
+ t.isHTML5 && t.isVideo && t.config.resetOnEnd && (t.restart(), t.pause());
2416
+ }), T.call(t, t.media, "progress playing seeking seeked", (s) => d.updateProgress.call(t, s)), T.call(t, t.media, "volumechange", (s) => d.updateVolume.call(t, s)), T.call(t, t.media, "playing play pause ended emptied timeupdate", (s) => S.checkPlaying.call(t, s)), T.call(t, t.media, "waiting canplay seeked playing", (s) => S.checkLoading.call(t, s)), t.supported.ui && t.config.clickToPlay && !t.isAudio) {
2417
+ const s = I.call(t, `.${t.config.classNames.video}`);
2418
+ if (!r.element(s))
2419
+ return;
2420
+ T.call(t, i.container, "click", (a) => {
2421
+ ![i.container, s].includes(a.target) && !s.contains(a.target) || t.touch && t.config.hideControls || (t.ended ? (this.proxy(a, t.restart, "restart"), this.proxy(
2422
+ a,
2423
+ () => {
2424
+ F(t.play());
2425
+ },
2426
+ "play"
2427
+ )) : this.proxy(
2428
+ a,
2429
+ () => {
2430
+ F(t.togglePlay());
2431
+ },
2432
+ "play"
2433
+ ));
2434
+ });
2435
+ }
2436
+ t.supported.ui && t.config.disableContextMenu && T.call(
2437
+ t,
2438
+ i.wrapper,
2439
+ "contextmenu",
2440
+ (s) => {
2441
+ s.preventDefault();
2442
+ },
2443
+ !1
2444
+ ), T.call(t, t.media, "volumechange", () => {
2445
+ t.storage.set({
2446
+ volume: t.volume,
2447
+ muted: t.muted
2448
+ });
2449
+ }), T.call(t, t.media, "ratechange", () => {
2450
+ d.updateSetting.call(t, "speed"), t.storage.set({ speed: t.speed });
2451
+ }), T.call(t, t.media, "qualitychange", (s) => {
2452
+ d.updateSetting.call(t, "quality", null, s.detail.quality);
2453
+ }), T.call(t, t.media, "ready qualitychange", () => {
2454
+ d.setDownloadUrl.call(t);
2455
+ });
2456
+ const n = t.config.events.concat(["keyup", "keydown"]).join(" ");
2457
+ T.call(t, t.media, n, (s) => {
2458
+ let { detail: a = {} } = s;
2459
+ s.type === "error" && (a = t.media.error), y.call(t, i.container, s.type, !0, a);
2460
+ });
2461
+ });
2462
+ // Run default and custom handlers
2463
+ m(this, "proxy", (t, i, n) => {
2464
+ const { player: s } = this, a = s.config.listeners[n], l = r.function(a);
2465
+ let o = !0;
2466
+ l && (o = a.call(s, t)), o !== !1 && r.function(i) && i.call(s, t);
2467
+ });
2468
+ // Trigger custom and default handlers
2469
+ m(this, "bind", (t, i, n, s, a = !0) => {
2470
+ const { player: l } = this, o = l.config.listeners[s], c = r.function(o);
2471
+ T.call(
2472
+ l,
2473
+ t,
2474
+ i,
2475
+ (u) => this.proxy(u, n, s),
2476
+ a && !c
2477
+ );
2478
+ });
2479
+ // Listen for control events
2480
+ m(this, "controls", () => {
2481
+ const { player: t } = this, { elements: i } = t, n = _.isIE ? "change" : "input";
2482
+ if (i.buttons.play && Array.from(i.buttons.play).forEach((s) => {
2483
+ this.bind(
2484
+ s,
2485
+ "click",
2486
+ () => {
2487
+ F(t.togglePlay());
2488
+ },
2489
+ "play"
2490
+ );
2491
+ }), this.bind(i.buttons.restart, "click", t.restart, "restart"), this.bind(
2492
+ i.buttons.rewind,
2493
+ "click",
2494
+ () => {
2495
+ t.lastSeekTime = Date.now(), t.rewind();
2496
+ },
2497
+ "rewind"
2498
+ ), this.bind(
2499
+ i.buttons.fastForward,
2500
+ "click",
2501
+ () => {
2502
+ t.lastSeekTime = Date.now(), t.forward();
2503
+ },
2504
+ "fastForward"
2505
+ ), this.bind(
2506
+ i.buttons.mute,
2507
+ "click",
2508
+ () => {
2509
+ t.muted = !t.muted;
2510
+ },
2511
+ "mute"
2512
+ ), this.bind(i.buttons.captions, "click", () => t.toggleCaptions()), this.bind(
2513
+ i.buttons.download,
2514
+ "click",
2515
+ () => {
2516
+ y.call(t, t.media, "download");
2517
+ },
2518
+ "download"
2519
+ ), this.bind(
2520
+ i.buttons.fullscreen,
2521
+ "click",
2522
+ () => {
2523
+ t.fullscreen.toggle();
2524
+ },
2525
+ "fullscreen"
2526
+ ), this.bind(
2527
+ i.buttons.pip,
2528
+ "click",
2529
+ () => {
2530
+ t.pip = "toggle";
2531
+ },
2532
+ "pip"
2533
+ ), this.bind(i.buttons.airplay, "click", t.airplay, "airplay"), this.bind(
2534
+ i.buttons.settings,
2535
+ "click",
2536
+ (s) => {
2537
+ s.stopPropagation(), s.preventDefault(), d.toggleMenu.call(t, s);
2538
+ },
2539
+ null,
2540
+ !1
2541
+ ), this.bind(
2542
+ i.buttons.settings,
2543
+ "keyup",
2544
+ (s) => {
2545
+ if ([" ", "Enter"].includes(s.key)) {
2546
+ if (s.key === "Enter") {
2547
+ d.focusFirstMenuItem.call(t, null, !0);
2548
+ return;
2549
+ }
2550
+ s.preventDefault(), s.stopPropagation(), d.toggleMenu.call(t, s);
2551
+ }
2552
+ },
2553
+ null,
2554
+ !1
2555
+ // Can't be passive as we're preventing default
2556
+ ), this.bind(i.settings.menu, "keydown", (s) => {
2557
+ s.key === "Escape" && d.toggleMenu.call(t, s);
2558
+ }), this.bind(i.inputs.seek, "mousedown mousemove", (s) => {
2559
+ const a = i.progress.getBoundingClientRect(), l = s.pageX - s.clientX, o = 100 / a.width * (s.pageX - a.left - l);
2560
+ s.currentTarget.setAttribute("seek-value", o);
2561
+ }), this.bind(i.inputs.seek, "mousedown mouseup keydown keyup touchstart touchend", (s) => {
2562
+ const a = s.currentTarget, l = "play-on-seeked";
2563
+ if (r.keyboardEvent(s) && !["ArrowLeft", "ArrowRight"].includes(s.key))
2564
+ return;
2565
+ t.lastSeekTime = Date.now();
2566
+ const o = a.hasAttribute(l), c = ["mouseup", "touchend", "keyup"].includes(s.type);
2567
+ o && c ? (a.removeAttribute(l), F(t.play())) : !c && t.playing && (a.setAttribute(l, ""), t.pause());
2568
+ }), _.isIos) {
2569
+ const s = Z.call(t, 'input[type="range"]');
2570
+ Array.from(s).forEach((a) => this.bind(a, n, (l) => et(l.target)));
2571
+ }
2572
+ this.bind(
2573
+ i.inputs.seek,
2574
+ n,
2575
+ (s) => {
2576
+ const a = s.currentTarget;
2577
+ let l = a.getAttribute("seek-value");
2578
+ r.empty(l) && (l = a.value), a.removeAttribute("seek-value"), t.currentTime = l / a.max * t.duration;
2579
+ },
2580
+ "seek"
2581
+ ), this.bind(i.progress, "mouseenter mouseleave mousemove", (s) => d.updateSeekTooltip.call(t, s)), this.bind(i.progress, "mousemove touchmove", (s) => {
2582
+ const { previewThumbnails: a } = t;
2583
+ a && a.loaded && a.startMove(s);
2584
+ }), this.bind(i.progress, "mouseleave touchend click", () => {
2585
+ const { previewThumbnails: s } = t;
2586
+ s && s.loaded && s.endMove(!1, !0);
2587
+ }), this.bind(i.progress, "mousedown touchstart", (s) => {
2588
+ const { previewThumbnails: a } = t;
2589
+ a && a.loaded && a.startScrubbing(s);
2590
+ }), this.bind(i.progress, "mouseup touchend", (s) => {
2591
+ const { previewThumbnails: a } = t;
2592
+ a && a.loaded && a.endScrubbing(s);
2593
+ }), _.isWebKit && Array.from(Z.call(t, 'input[type="range"]')).forEach((s) => {
2594
+ this.bind(s, "input", (a) => d.updateRangeFill.call(t, a.target));
2595
+ }), t.config.toggleInvert && !r.element(i.display.duration) && this.bind(i.display.currentTime, "click", () => {
2596
+ t.currentTime !== 0 && (t.config.invertTime = !t.config.invertTime, d.timeUpdate.call(t));
2597
+ }), this.bind(
2598
+ i.inputs.volume,
2599
+ n,
2600
+ (s) => {
2601
+ t.volume = s.target.value;
2602
+ },
2603
+ "volume"
2604
+ ), this.bind(i.controls, "mouseenter mouseleave", (s) => {
2605
+ i.controls.hover = !t.touch && s.type === "mouseenter";
2606
+ }), i.fullscreen && Array.from(i.fullscreen.children).filter((s) => !s.contains(i.container)).forEach((s) => {
2607
+ this.bind(s, "mouseenter mouseleave", (a) => {
2608
+ i.controls && (i.controls.hover = !t.touch && a.type === "mouseenter");
2609
+ });
2610
+ }), this.bind(i.controls, "mousedown mouseup touchstart touchend touchcancel", (s) => {
2611
+ i.controls.pressed = ["mousedown", "touchstart"].includes(s.type);
2612
+ }), this.bind(i.controls, "focusin", () => {
2613
+ const { config: s, timers: a } = t;
2614
+ E(i.controls, s.classNames.noTransition, !0), S.toggleControls.call(t, !0), setTimeout(() => {
2615
+ E(i.controls, s.classNames.noTransition, !1);
2616
+ }, 0);
2617
+ const l = this.touch ? 3e3 : 4e3;
2618
+ clearTimeout(a.controls), a.controls = setTimeout(() => S.toggleControls.call(t, !1), l);
2619
+ }), this.bind(
2620
+ i.inputs.volume,
2621
+ "wheel",
2622
+ (s) => {
2623
+ const a = s.webkitDirectionInvertedFromDevice, [l, o] = [s.deltaX, -s.deltaY].map((f) => a ? -f : f), c = Math.sign(Math.abs(l) > Math.abs(o) ? l : o);
2624
+ t.increaseVolume(c / 50);
2625
+ const { volume: u } = t.media;
2626
+ (c === 1 && u < 1 || c === -1 && u > 0) && s.preventDefault();
2627
+ },
2628
+ "volume",
2629
+ !1
2630
+ );
2631
+ });
2632
+ this.player = t, this.lastKey = null, this.focusTimer = null, this.lastKeyDown = null, this.handleKey = this.handleKey.bind(this), this.toggleMenu = this.toggleMenu.bind(this), this.firstTouch = this.firstTouch.bind(this);
2633
+ }
2634
+ // Handle key presses
2635
+ handleKey(t) {
2636
+ const { player: i } = this, { elements: n } = i, { key: s, type: a, altKey: l, ctrlKey: o, metaKey: c, shiftKey: u } = t, f = a === "keydown", w = f && s === this.lastKey;
2637
+ if (l || o || c || u || !s)
2638
+ return;
2639
+ const h = (g) => {
2640
+ i.currentTime = i.duration / 10 * g;
2641
+ };
2642
+ if (f) {
2643
+ const g = document.activeElement;
2644
+ if (r.element(g)) {
2645
+ const { editable: A } = i.config.selectors, { seek: x } = n.inputs;
2646
+ if (g !== x && Y(g, A) || t.key === " " && Y(g, 'button, [role^="menuitem"]'))
2647
+ return;
2648
+ }
2649
+ switch ([
2650
+ " ",
2651
+ "ArrowLeft",
2652
+ "ArrowUp",
2653
+ "ArrowRight",
2654
+ "ArrowDown",
2655
+ "0",
2656
+ "1",
2657
+ "2",
2658
+ "3",
2659
+ "4",
2660
+ "5",
2661
+ "6",
2662
+ "7",
2663
+ "8",
2664
+ "9",
2665
+ "c",
2666
+ "f",
2667
+ "k",
2668
+ "l",
2669
+ "m"
2670
+ ].includes(s) && (t.preventDefault(), t.stopPropagation()), s) {
2671
+ case "0":
2672
+ case "1":
2673
+ case "2":
2674
+ case "3":
2675
+ case "4":
2676
+ case "5":
2677
+ case "6":
2678
+ case "7":
2679
+ case "8":
2680
+ case "9":
2681
+ w || h(Number.parseInt(s, 10));
2682
+ break;
2683
+ case " ":
2684
+ case "k":
2685
+ w || F(i.togglePlay());
2686
+ break;
2687
+ case "ArrowUp":
2688
+ i.increaseVolume(0.1);
2689
+ break;
2690
+ case "ArrowDown":
2691
+ i.decreaseVolume(0.1);
2692
+ break;
2693
+ case "m":
2694
+ w || (i.muted = !i.muted);
2695
+ break;
2696
+ case "ArrowRight":
2697
+ i.forward();
2698
+ break;
2699
+ case "ArrowLeft":
2700
+ i.rewind();
2701
+ break;
2702
+ case "f":
2703
+ i.fullscreen.toggle();
2704
+ break;
2705
+ case "c":
2706
+ w || i.toggleCaptions();
2707
+ break;
2708
+ case "l":
2709
+ i.loop = !i.loop;
2710
+ break;
2711
+ }
2712
+ s === "Escape" && !i.fullscreen.usingNative && i.fullscreen.active && i.fullscreen.toggle(), this.lastKey = s;
2713
+ } else
2714
+ this.lastKey = null;
2715
+ }
2716
+ // Toggle menu
2717
+ toggleMenu(t) {
2718
+ d.toggleMenu.call(this.player, t);
2719
+ }
2720
+ }
2721
+ var oe = { exports: {} }, mi = oe.exports, Fe;
2722
+ function pi() {
2723
+ return Fe || (Fe = 1, (function(e, t) {
2724
+ (function(i, n) {
2725
+ e.exports = n();
2726
+ })(mi, function() {
2727
+ var i = function() {
2728
+ }, n = {}, s = {}, a = {};
2729
+ function l(h, g) {
2730
+ h = h.push ? h : [h];
2731
+ var v = [], A = h.length, x = A, P, p, k, M;
2732
+ for (P = function(j, R) {
2733
+ R.length && v.push(j), x--, x || g(v);
2734
+ }; A--; ) {
2735
+ if (p = h[A], k = s[p], k) {
2736
+ P(p, k);
2737
+ continue;
2738
+ }
2739
+ M = a[p] = a[p] || [], M.push(P);
2740
+ }
2741
+ }
2742
+ function o(h, g) {
2743
+ if (h) {
2744
+ var v = a[h];
2745
+ if (s[h] = g, !!v)
2746
+ for (; v.length; )
2747
+ v[0](h, g), v.splice(0, 1);
2748
+ }
2749
+ }
2750
+ function c(h, g) {
2751
+ h.call && (h = { success: h }), g.length ? (h.error || i)(g) : (h.success || i)(h);
2752
+ }
2753
+ function u(h, g, v, A) {
2754
+ var x = document, P = v.async, p = (v.numRetries || 0) + 1, k = v.before || i, M = h.replace(/[\?|#].*$/, ""), j = h.replace(/^(css|img|module|nomodule)!/, ""), R, H, N;
2755
+ if (A = A || 0, /(^css!|\.css$)/.test(M))
2756
+ N = x.createElement("link"), N.rel = "stylesheet", N.href = j, R = "hideFocus" in N, R && N.relList && (R = 0, N.rel = "preload", N.as = "style");
2757
+ else if (/(^img!|\.(png|gif|jpg|svg|webp)$)/.test(M))
2758
+ N = x.createElement("img"), N.src = j;
2759
+ else if (N = x.createElement("script"), N.src = j, N.async = P === void 0 ? !0 : P, H = "noModule" in N, /^module!/.test(M)) {
2760
+ if (!H) return g(h, "l");
2761
+ N.type = "module";
2762
+ } else if (/^nomodule!/.test(M) && H) return g(h, "l");
2763
+ N.onload = N.onerror = N.onbeforeload = function(Ie) {
2764
+ var re = Ie.type[0];
2765
+ if (R)
2766
+ try {
2767
+ N.sheet.cssText.length || (re = "e");
2768
+ } catch (ft) {
2769
+ ft.code != 18 && (re = "e");
2770
+ }
2771
+ if (re == "e") {
2772
+ if (A += 1, A < p)
2773
+ return u(h, g, v, A);
2774
+ } else if (N.rel == "preload" && N.as == "style")
2775
+ return N.rel = "stylesheet";
2776
+ g(h, re, Ie.defaultPrevented);
2777
+ }, k(h, N) !== !1 && x.head.appendChild(N);
2778
+ }
2779
+ function f(h, g, v) {
2780
+ h = h.push ? h : [h];
2781
+ var A = h.length, x = A, P = [], p, k;
2782
+ for (p = function(M, j, R) {
2783
+ if (j == "e" && P.push(M), j == "b")
2784
+ if (R) P.push(M);
2785
+ else return;
2786
+ A--, A || g(P);
2787
+ }, k = 0; k < x; k++) u(h[k], p, v);
2788
+ }
2789
+ function w(h, g, v) {
2790
+ var A, x;
2791
+ if (g && g.trim && (A = g), x = (A ? v : g) || {}, A) {
2792
+ if (A in n)
2793
+ throw "LoadJS";
2794
+ n[A] = !0;
2795
+ }
2796
+ function P(p, k) {
2797
+ f(h, function(M) {
2798
+ c(x, M), p && c({ success: p, error: k }, M), o(A, M);
2799
+ }, x);
2800
+ }
2801
+ if (x.returnPromise) return new Promise(P);
2802
+ P();
2803
+ }
2804
+ return w.ready = function(g, v) {
2805
+ return l(g, function(A) {
2806
+ c(v, A);
2807
+ }), w;
2808
+ }, w.done = function(g) {
2809
+ o(g, []);
2810
+ }, w.reset = function() {
2811
+ n = {}, s = {}, a = {};
2812
+ }, w.isDefined = function(g) {
2813
+ return g in n;
2814
+ }, w;
2815
+ });
2816
+ })(oe)), oe.exports;
2817
+ }
2818
+ var fi = pi();
2819
+ const gi = /* @__PURE__ */ yt(fi);
2820
+ function $e(e) {
2821
+ return new Promise((t, i) => {
2822
+ gi(e, {
2823
+ success: t,
2824
+ error: i
2825
+ });
2826
+ });
2827
+ }
2828
+ function bi(e) {
2829
+ if (r.empty(e))
2830
+ return null;
2831
+ if (r.number(Number(e)))
2832
+ return e;
2833
+ const t = /^.*(vimeo.com\/|video\/)(\d+).*/, i = e.match(t);
2834
+ return i ? i[2] : e;
2835
+ }
2836
+ function yi(e) {
2837
+ const t = /^.*(vimeo.com\/|video\/)(\d+)(\?.*h=|\/)+([\d,a-f]+)/, i = e.match(t);
2838
+ return i && i.length === 5 ? i[4] : null;
2839
+ }
2840
+ function Q(e) {
2841
+ e && !this.embed.hasPlayed && (this.embed.hasPlayed = !0), this.media.paused === e && (this.media.paused = !e, y.call(this, this.media, e ? "play" : "pause"));
2842
+ }
2843
+ const Ee = {
2844
+ setup() {
2845
+ const e = this;
2846
+ E(e.elements.wrapper, e.config.classNames.embed, !0), e.options.speed = e.config.speed.options, X.call(e), r.object(window.Vimeo) ? Ee.ready.call(e) : $e(e.config.urls.vimeo.sdk).then(() => {
2847
+ Ee.ready.call(e);
2848
+ }).catch((t) => {
2849
+ e.debug.warn("Vimeo SDK (player.js) failed to load", t);
2850
+ });
2851
+ },
2852
+ // API Ready
2853
+ ready() {
2854
+ const e = this, t = e.config.vimeo, { premium: i, referrerPolicy: n, ...s } = t;
2855
+ let a = e.media.getAttribute("src"), l = "";
2856
+ r.empty(a) ? (a = e.media.getAttribute(e.config.attributes.embed.id), l = e.media.getAttribute(e.config.attributes.embed.hash)) : l = yi(a);
2857
+ const o = l ? { h: l } : {};
2858
+ i && Object.assign(s, {
2859
+ controls: !1,
2860
+ sidedock: !1
2861
+ });
2862
+ const c = ht({
2863
+ loop: e.config.loop.active,
2864
+ autoplay: e.autoplay,
2865
+ muted: e.muted,
2866
+ gesture: "media",
2867
+ playsinline: e.config.playsinline,
2868
+ // hash has to be added to iframe-URL
2869
+ ...o,
2870
+ ...s
2871
+ }), u = bi(a), f = b("iframe"), w = Ae(e.config.urls.vimeo.iframe, u, c);
2872
+ if (f.setAttribute("src", w), f.setAttribute("allowfullscreen", ""), f.setAttribute(
2873
+ "allow",
2874
+ ["autoplay", "fullscreen", "picture-in-picture", "encrypted-media", "accelerometer", "gyroscope"].join("; ")
2875
+ ), r.empty(n) || f.setAttribute("referrerPolicy", n), i || !t.customControls)
2876
+ f.setAttribute("data-poster", e.poster), e.media = ue(f, e.media);
2877
+ else {
2878
+ const p = b("div", {
2879
+ class: e.config.classNames.embedContainer,
2880
+ "data-poster": e.poster
2881
+ });
2882
+ p.appendChild(f), e.media = ue(p, e.media);
2883
+ }
2884
+ t.customControls || ne(Ae(e.config.urls.vimeo.api, w)).then((p) => {
2885
+ r.empty(p) || !p.thumbnail_url || S.setPoster.call(e, p.thumbnail_url).catch(() => {
2886
+ });
2887
+ }), e.embed = new window.Vimeo.Player(f, {
2888
+ autopause: e.config.autopause,
2889
+ muted: e.muted
2890
+ }), e.media.paused = !0, e.media.currentTime = 0, e.supported.ui && e.embed.disableTextTrack(), e.media.play = () => (Q.call(e, !0), e.embed.play()), e.media.pause = () => (Q.call(e, !1), e.embed.pause()), e.media.stop = () => {
2891
+ e.pause(), e.currentTime = 0;
2892
+ };
2893
+ let { currentTime: h } = e.media;
2894
+ Object.defineProperty(e.media, "currentTime", {
2895
+ get() {
2896
+ return h;
2897
+ },
2898
+ set(p) {
2899
+ const { embed: k, media: M, paused: j, volume: R } = e, H = j && !k.hasPlayed;
2900
+ M.seeking = !0, y.call(e, M, "seeking"), Promise.resolve(H && k.setVolume(0)).then(() => k.setCurrentTime(p)).then(() => H && k.pause()).then(() => H && k.setVolume(R)).catch(() => {
2901
+ });
2902
+ }
2903
+ });
2904
+ let g = e.config.speed.selected;
2905
+ Object.defineProperty(e.media, "playbackRate", {
2906
+ get() {
2907
+ return g;
2908
+ },
2909
+ set(p) {
2910
+ e.embed.setPlaybackRate(p).then(() => {
2911
+ g = p, y.call(e, e.media, "ratechange");
2912
+ }).catch(() => {
2913
+ e.options.speed = [1];
2914
+ });
2915
+ }
2916
+ });
2917
+ let { volume: v } = e.config;
2918
+ Object.defineProperty(e.media, "volume", {
2919
+ get() {
2920
+ return v;
2921
+ },
2922
+ set(p) {
2923
+ e.embed.setVolume(p).then(() => {
2924
+ v = p, y.call(e, e.media, "volumechange");
2925
+ });
2926
+ }
2927
+ });
2928
+ let { muted: A } = e.config;
2929
+ Object.defineProperty(e.media, "muted", {
2930
+ get() {
2931
+ return A;
2932
+ },
2933
+ set(p) {
2934
+ const k = r.boolean(p) ? p : !1;
2935
+ e.embed.setMuted(k ? !0 : e.config.muted).then(() => {
2936
+ A = k, y.call(e, e.media, "volumechange");
2937
+ });
2938
+ }
2939
+ });
2940
+ let { loop: x } = e.config;
2941
+ Object.defineProperty(e.media, "loop", {
2942
+ get() {
2943
+ return x;
2944
+ },
2945
+ set(p) {
2946
+ const k = r.boolean(p) ? p : e.config.loop.active;
2947
+ e.embed.setLoop(k).then(() => {
2948
+ x = k;
2949
+ });
2950
+ }
2951
+ });
2952
+ let P;
2953
+ e.embed.getVideoUrl().then((p) => {
2954
+ P = p, d.setDownloadUrl.call(e);
2955
+ }).catch((p) => {
2956
+ this.debug.warn(p);
2957
+ }), Object.defineProperty(e.media, "currentSrc", {
2958
+ get() {
2959
+ return P;
2960
+ }
2961
+ }), Object.defineProperty(e.media, "ended", {
2962
+ get() {
2963
+ return e.currentTime === e.duration;
2964
+ }
2965
+ }), Promise.all([e.embed.getVideoWidth(), e.embed.getVideoHeight()]).then((p) => {
2966
+ const [k, M] = p;
2967
+ e.embed.ratio = at(k, M), X.call(this);
2968
+ }), e.embed.setAutopause(e.config.autopause).then((p) => {
2969
+ e.config.autopause = p;
2970
+ }), e.embed.getVideoTitle().then((p) => {
2971
+ e.config.title = p, S.setTitle.call(this);
2972
+ }), e.embed.getCurrentTime().then((p) => {
2973
+ h = p, y.call(e, e.media, "timeupdate");
2974
+ }), e.embed.getDuration().then((p) => {
2975
+ e.media.duration = p, y.call(e, e.media, "durationchange");
2976
+ }), e.embed.getTextTracks().then((p) => {
2977
+ e.media.textTracks = p, C.setup.call(e);
2978
+ }), e.embed.on("cuechange", ({ cues: p = [] }) => {
2979
+ const k = p.map((M) => ai(M.text));
2980
+ C.updateCues.call(e, k);
2981
+ }), e.embed.on("loaded", () => {
2982
+ e.embed.getPaused().then((p) => {
2983
+ Q.call(e, !p), p || y.call(e, e.media, "playing");
2984
+ }), r.element(e.embed.element) && e.supported.ui && e.embed.element.setAttribute("tabindex", -1);
2985
+ }), e.embed.on("bufferstart", () => {
2986
+ y.call(e, e.media, "waiting");
2987
+ }), e.embed.on("bufferend", () => {
2988
+ y.call(e, e.media, "playing");
2989
+ }), e.embed.on("play", () => {
2990
+ Q.call(e, !0), y.call(e, e.media, "playing");
2991
+ }), e.embed.on("pause", () => {
2992
+ Q.call(e, !1);
2993
+ }), e.embed.on("timeupdate", (p) => {
2994
+ e.media.seeking = !1, h = p.seconds, y.call(e, e.media, "timeupdate");
2995
+ }), e.embed.on("progress", (p) => {
2996
+ e.media.buffered = p.percent, y.call(e, e.media, "progress"), Number.parseInt(p.percent, 10) === 1 && y.call(e, e.media, "canplaythrough"), e.embed.getDuration().then((k) => {
2997
+ k !== e.media.duration && (e.media.duration = k, y.call(e, e.media, "durationchange"));
2998
+ });
2999
+ }), e.embed.on("seeked", () => {
3000
+ e.media.seeking = !1, y.call(e, e.media, "seeked");
3001
+ }), e.embed.on("ended", () => {
3002
+ e.media.paused = !0, y.call(e, e.media, "ended");
3003
+ }), e.embed.on("error", (p) => {
3004
+ e.media.error = p, y.call(e, e.media, "error");
3005
+ }), t.customControls && setTimeout(() => S.build.call(e), 0);
3006
+ }
3007
+ };
3008
+ function wi(e) {
3009
+ if (r.empty(e))
3010
+ return null;
3011
+ const t = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/, i = e.match(t);
3012
+ return i && i[2] ? i[2] : e;
3013
+ }
3014
+ function J(e) {
3015
+ e && !this.embed.hasPlayed && (this.embed.hasPlayed = !0), this.media.paused === e && (this.media.paused = !e, y.call(this, this.media, e ? "play" : "pause"));
3016
+ }
3017
+ function vi(e) {
3018
+ if (e.noCookie)
3019
+ return "https://www.youtube-nocookie.com";
3020
+ if (window.location.protocol === "http:")
3021
+ return "http://www.youtube.com";
3022
+ }
3023
+ const ce = {
3024
+ setup() {
3025
+ if (E(this.elements.wrapper, this.config.classNames.embed, !0), r.object(window.YT) && r.function(window.YT.Player))
3026
+ ce.ready.call(this);
3027
+ else {
3028
+ const e = window.onYouTubeIframeAPIReady;
3029
+ window.onYouTubeIframeAPIReady = () => {
3030
+ r.function(e) && e(), ce.ready.call(this);
3031
+ }, $e(this.config.urls.youtube.sdk).catch((t) => {
3032
+ this.debug.warn("YouTube API failed to load", t);
3033
+ });
3034
+ }
3035
+ },
3036
+ // Get the media title
3037
+ getTitle(e) {
3038
+ const t = Ae(this.config.urls.youtube.api, e);
3039
+ ne(t).then((i) => {
3040
+ if (r.object(i)) {
3041
+ const { title: n, height: s, width: a } = i;
3042
+ this.config.title = n, S.setTitle.call(this), this.embed.ratio = at(a, s);
3043
+ }
3044
+ X.call(this);
3045
+ }).catch(() => {
3046
+ X.call(this);
3047
+ });
3048
+ },
3049
+ // API ready
3050
+ ready() {
3051
+ const e = this, t = e.config.youtube, i = e.media && e.media.getAttribute("id");
3052
+ if (!r.empty(i) && i.startsWith("youtube-"))
3053
+ return;
3054
+ let n = e.media.getAttribute("src");
3055
+ r.empty(n) && (n = e.media.getAttribute(this.config.attributes.embed.id));
3056
+ const s = wi(n), a = ii(e.provider), l = b("div", { id: a, "data-poster": t.customControls ? e.poster : void 0 });
3057
+ if (e.media = ue(l, e.media), t.customControls) {
3058
+ const o = (c) => `https://i.ytimg.com/vi/${s}/${c}default.jpg`;
3059
+ le(o("maxres"), 121).catch(() => le(o("sd"), 121)).catch(() => le(o("hq"))).then((c) => S.setPoster.call(e, c.src)).then((c) => {
3060
+ c.includes("maxres") || (e.elements.poster.style.backgroundSize = "cover");
3061
+ }).catch(() => {
3062
+ });
3063
+ }
3064
+ e.embed = new window.YT.Player(e.media, {
3065
+ videoId: s,
3066
+ host: vi(t),
3067
+ playerVars: L(
3068
+ {},
3069
+ {
3070
+ // Autoplay
3071
+ autoplay: e.config.autoplay ? 1 : 0,
3072
+ // iframe interface language
3073
+ hl: e.config.hl,
3074
+ // Only show controls if not fully supported or opted out
3075
+ controls: e.supported.ui && t.customControls ? 0 : 1,
3076
+ // Disable keyboard as we handle it
3077
+ disablekb: 1,
3078
+ // Allow iOS inline playback
3079
+ playsinline: e.config.playsinline && !e.config.fullscreen.iosNative ? 1 : 0,
3080
+ // Captions are flaky on YouTube
3081
+ cc_load_policy: e.captions.active ? 1 : 0,
3082
+ cc_lang_pref: e.config.captions.language,
3083
+ // Tracking for stats
3084
+ widget_referrer: window ? window.location.href : null
3085
+ },
3086
+ t
3087
+ ),
3088
+ events: {
3089
+ onError(o) {
3090
+ if (!e.media.error) {
3091
+ const c = o.data, u = {
3092
+ 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.",
3093
+ 5: "The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.",
3094
+ 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.",
3095
+ 101: "The owner of the requested video does not allow it to be played in embedded players.",
3096
+ 150: "The owner of the requested video does not allow it to be played in embedded players."
3097
+ }[c] || "An unknown error occurred";
3098
+ e.media.error = { code: c, message: u }, y.call(e, e.media, "error");
3099
+ }
3100
+ },
3101
+ onPlaybackRateChange(o) {
3102
+ const c = o.target;
3103
+ e.media.playbackRate = c.getPlaybackRate(), y.call(e, e.media, "ratechange");
3104
+ },
3105
+ onReady(o) {
3106
+ if (r.function(e.media.play))
3107
+ return;
3108
+ const c = o.target;
3109
+ ce.getTitle.call(e, s), e.media.play = () => {
3110
+ J.call(e, !0), c.playVideo();
3111
+ }, e.media.pause = () => {
3112
+ J.call(e, !1), c.pauseVideo();
3113
+ }, e.media.stop = () => {
3114
+ c.stopVideo();
3115
+ }, e.media.duration = c.getDuration(), e.media.paused = !0, e.media.currentTime = 0, Object.defineProperty(e.media, "currentTime", {
3116
+ get() {
3117
+ return Number(c.getCurrentTime());
3118
+ },
3119
+ set(h) {
3120
+ e.paused && !e.embed.hasPlayed && e.embed.mute(), e.media.seeking = !0, y.call(e, e.media, "seeking"), c.seekTo(h);
3121
+ }
3122
+ }), Object.defineProperty(e.media, "playbackRate", {
3123
+ get() {
3124
+ return c.getPlaybackRate();
3125
+ },
3126
+ set(h) {
3127
+ c.setPlaybackRate(h);
3128
+ }
3129
+ });
3130
+ let { volume: u } = e.config;
3131
+ Object.defineProperty(e.media, "volume", {
3132
+ get() {
3133
+ return u;
3134
+ },
3135
+ set(h) {
3136
+ u = h, c.setVolume(u * 100), y.call(e, e.media, "volumechange");
3137
+ }
3138
+ });
3139
+ let { muted: f } = e.config;
3140
+ Object.defineProperty(e.media, "muted", {
3141
+ get() {
3142
+ return f;
3143
+ },
3144
+ set(h) {
3145
+ const g = r.boolean(h) ? h : f;
3146
+ f = g, c[g ? "mute" : "unMute"](), c.setVolume(u * 100), y.call(e, e.media, "volumechange");
3147
+ }
3148
+ }), Object.defineProperty(e.media, "currentSrc", {
3149
+ get() {
3150
+ return c.getVideoUrl();
3151
+ }
3152
+ }), Object.defineProperty(e.media, "ended", {
3153
+ get() {
3154
+ return e.currentTime === e.duration;
3155
+ }
3156
+ });
3157
+ const w = c.getAvailablePlaybackRates();
3158
+ e.options.speed = w.filter((h) => e.config.speed.options.includes(h)), e.supported.ui && t.customControls && e.media.setAttribute("tabindex", -1), y.call(e, e.media, "timeupdate"), y.call(e, e.media, "durationchange"), clearInterval(e.timers.buffering), e.timers.buffering = setInterval(() => {
3159
+ e.media.buffered = c.getVideoLoadedFraction(), (e.media.lastBuffered === null || e.media.lastBuffered < e.media.buffered) && y.call(e, e.media, "progress"), e.media.lastBuffered = e.media.buffered, e.media.buffered === 1 && (clearInterval(e.timers.buffering), y.call(e, e.media, "canplaythrough"));
3160
+ }, 200), t.customControls && setTimeout(() => S.build.call(e), 50);
3161
+ },
3162
+ onStateChange(o) {
3163
+ const c = o.target;
3164
+ switch (clearInterval(e.timers.playing), e.media.seeking && [1, 2].includes(o.data) && (e.media.seeking = !1, y.call(e, e.media, "seeked")), o.data) {
3165
+ case -1:
3166
+ y.call(e, e.media, "timeupdate"), e.media.buffered = c.getVideoLoadedFraction(), y.call(e, e.media, "progress");
3167
+ break;
3168
+ case 0:
3169
+ J.call(e, !1), e.media.loop ? (c.stopVideo(), c.playVideo()) : y.call(e, e.media, "ended");
3170
+ break;
3171
+ case 1:
3172
+ t.customControls && !e.config.autoplay && e.media.paused && !e.embed.hasPlayed ? e.media.pause() : (J.call(e, !0), y.call(e, e.media, "playing"), e.timers.playing = setInterval(() => {
3173
+ y.call(e, e.media, "timeupdate");
3174
+ }, 50), e.media.duration !== c.getDuration() && (e.media.duration = c.getDuration(), y.call(e, e.media, "durationchange")));
3175
+ break;
3176
+ case 2:
3177
+ e.muted || e.embed.unMute(), J.call(e, !1);
3178
+ break;
3179
+ case 3:
3180
+ y.call(e, e.media, "waiting");
3181
+ break;
3182
+ }
3183
+ y.call(e, e.elements.container, "statechange", !1, {
3184
+ code: o.data
3185
+ });
3186
+ }
3187
+ }
3188
+ });
3189
+ }
3190
+ }, mt = {
3191
+ // Setup media
3192
+ setup() {
3193
+ if (!this.media) {
3194
+ this.debug.warn("No media element found!");
3195
+ return;
3196
+ }
3197
+ E(this.elements.container, this.config.classNames.type.replace("{0}", this.type), !0), E(this.elements.container, this.config.classNames.provider.replace("{0}", this.provider), !0), this.isEmbed && E(this.elements.container, this.config.classNames.type.replace("{0}", "video"), !0), this.isVideo && (this.elements.wrapper = b("div", {
3198
+ class: this.config.classNames.video
3199
+ }), it(this.media, this.elements.wrapper), this.elements.poster = b("div", {
3200
+ class: this.config.classNames.poster
3201
+ }), this.elements.wrapper.appendChild(this.elements.poster)), this.isHTML5 ? z.setup.call(this) : this.isYouTube ? ce.setup.call(this) : this.isVimeo && Ee.setup.call(this);
3202
+ }
3203
+ };
3204
+ function ki(e) {
3205
+ e.manager && e.manager.destroy(), e.elements.displayContainer && e.elements.displayContainer.destroy(), e.elements.container.remove();
3206
+ }
3207
+ class Ti {
3208
+ /**
3209
+ * Ads constructor.
3210
+ * @param {object} player
3211
+ * @return {Ads}
3212
+ */
3213
+ constructor(t) {
3214
+ /**
3215
+ * Load the IMA SDK
3216
+ */
3217
+ m(this, "load", () => {
3218
+ this.enabled && (!r.object(window.google) || !r.object(window.google.ima) ? $e(this.player.config.urls.googleIMA.sdk).then(() => {
3219
+ this.ready();
3220
+ }).catch(() => {
3221
+ this.trigger("error", new Error("Google IMA SDK failed to load"));
3222
+ }) : this.ready());
3223
+ });
3224
+ /**
3225
+ * Get the ads instance ready
3226
+ */
3227
+ m(this, "ready", () => {
3228
+ this.enabled || ki(this), this.startSafetyTimer(12e3, "ready()"), this.managerPromise.then(() => {
3229
+ this.clearSafetyTimer("onAdsManagerLoaded()");
3230
+ }), this.listeners(), this.setupIMA();
3231
+ });
3232
+ /**
3233
+ * In order for the SDK to display ads for our video, we need to tell it where to put them,
3234
+ * so here we define our ad container. This div is set up to render on top of the video player.
3235
+ * Using the code below, we tell the SDK to render ads within that div. We also provide a
3236
+ * handle to the content video player - the SDK will poll the current time of our player to
3237
+ * properly place mid-rolls. After we create the ad display container, we initialize it. On
3238
+ * mobile devices, this initialization is done as the result of a user action.
3239
+ */
3240
+ m(this, "setupIMA", () => {
3241
+ this.elements.container = b("div", {
3242
+ class: this.player.config.classNames.ads
3243
+ }), 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(
3244
+ google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
3245
+ (t) => this.onAdsManagerLoaded(t),
3246
+ !1
3247
+ ), this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, (t) => this.onAdError(t), !1), this.requestAds();
3248
+ });
3249
+ /**
3250
+ * Request advertisements
3251
+ */
3252
+ m(this, "requestAds", () => {
3253
+ const { container: t } = this.player.elements;
3254
+ try {
3255
+ const i = new google.ima.AdsRequest();
3256
+ i.adTagUrl = this.tagUrl, i.linearAdSlotWidth = t.offsetWidth, i.linearAdSlotHeight = t.offsetHeight, i.nonLinearAdSlotWidth = t.offsetWidth, i.nonLinearAdSlotHeight = t.offsetHeight, i.forceNonLinearFullSlot = !1, i.setAdWillPlayMuted(!this.player.muted), this.loader.requestAds(i);
3257
+ } catch (i) {
3258
+ this.onAdError(i);
3259
+ }
3260
+ });
3261
+ /**
3262
+ * Update the ad countdown
3263
+ * @param {boolean} start
3264
+ */
3265
+ m(this, "pollCountdown", (t = !1) => {
3266
+ if (!t) {
3267
+ clearInterval(this.countdownTimer), this.elements.container.removeAttribute("data-badge-text");
3268
+ return;
3269
+ }
3270
+ const i = () => {
3271
+ const n = ge(Math.max(this.manager.getRemainingTime(), 0)), s = `${O.get("advertisement", this.player.config)} - ${n}`;
3272
+ this.elements.container.setAttribute("data-badge-text", s);
3273
+ };
3274
+ this.countdownTimer = setInterval(i, 100);
3275
+ });
3276
+ /**
3277
+ * This method is called whenever the ads are ready inside the AdDisplayContainer
3278
+ * @param {Event} event - adsManagerLoadedEvent
3279
+ */
3280
+ m(this, "onAdsManagerLoaded", (t) => {
3281
+ if (!this.enabled)
3282
+ return;
3283
+ const i = new google.ima.AdsRenderingSettings();
3284
+ i.restoreCustomPlaybackStateOnAdBreakComplete = !0, i.enablePreloading = !0, this.manager = t.getAdsManager(this.player, i), 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) => {
3285
+ this.manager.addEventListener(google.ima.AdEvent.Type[n], (s) => this.onAdEvent(s));
3286
+ }), this.trigger("loaded");
3287
+ });
3288
+ m(this, "addCuePoints", () => {
3289
+ r.empty(this.cuePoints) || this.cuePoints.forEach((t) => {
3290
+ if (t !== 0 && t !== -1 && t < this.player.duration) {
3291
+ const i = this.player.elements.progress;
3292
+ if (r.element(i)) {
3293
+ const n = 100 / this.player.duration * t, s = b("span", {
3294
+ class: this.player.config.classNames.cues
3295
+ });
3296
+ s.style.left = `${n.toString()}%`, i.appendChild(s);
3297
+ }
3298
+ }
3299
+ });
3300
+ });
3301
+ /**
3302
+ * This is where all the event handling takes place. Retrieve the ad from the event. Some
3303
+ * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated
3304
+ * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type
3305
+ * @param {Event} event
3306
+ */
3307
+ m(this, "onAdEvent", (t) => {
3308
+ const { container: i } = this.player.elements, n = t.getAd(), s = t.getAdData();
3309
+ switch (((l) => {
3310
+ y.call(this.player, this.player.media, `ads${l.replace(/_/g, "").toLowerCase()}`);
3311
+ })(t.type), t.type) {
3312
+ case google.ima.AdEvent.Type.LOADED:
3313
+ this.trigger("loaded"), this.pollCountdown(!0), n.isLinear() || (n.width = i.offsetWidth, n.height = i.offsetHeight);
3314
+ break;
3315
+ case google.ima.AdEvent.Type.STARTED:
3316
+ this.manager.setVolume(this.player.volume);
3317
+ break;
3318
+ case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:
3319
+ this.player.ended ? this.loadAds() : this.loader.contentComplete();
3320
+ break;
3321
+ case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:
3322
+ this.pauseContent();
3323
+ break;
3324
+ case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:
3325
+ this.pollCountdown(), this.resumeContent();
3326
+ break;
3327
+ case google.ima.AdEvent.Type.LOG:
3328
+ s.adError && this.player.debug.warn(`Non-fatal ad error: ${s.adError.getMessage()}`);
3329
+ break;
3330
+ }
3331
+ });
3332
+ /**
3333
+ * Any ad error handling comes through here
3334
+ * @param {Event} event
3335
+ */
3336
+ m(this, "onAdError", (t) => {
3337
+ this.cancel(), this.player.debug.warn("Ads error", t);
3338
+ });
3339
+ /**
3340
+ * Setup hooks for Plyr and window events. This ensures
3341
+ * the mid- and post-roll launch at the correct time. And
3342
+ * resize the advertisement when the player resizes
3343
+ */
3344
+ m(this, "listeners", () => {
3345
+ const { container: t } = this.player.elements;
3346
+ let i;
3347
+ this.player.on("canplay", () => {
3348
+ this.addCuePoints();
3349
+ }), this.player.on("ended", () => {
3350
+ this.loader.contentComplete();
3351
+ }), this.player.on("timeupdate", () => {
3352
+ i = this.player.currentTime;
3353
+ }), this.player.on("seeked", () => {
3354
+ const n = this.player.currentTime;
3355
+ r.empty(this.cuePoints) || this.cuePoints.forEach((s, a) => {
3356
+ i < s && s < n && (this.manager.discardAdBreak(), this.cuePoints.splice(a, 1));
3357
+ });
3358
+ }), window.addEventListener("resize", () => {
3359
+ this.manager && this.manager.resize(t.offsetWidth, t.offsetHeight, google.ima.ViewMode.NORMAL);
3360
+ });
3361
+ });
3362
+ /**
3363
+ * Initialize the adsManager and start playing advertisements
3364
+ */
3365
+ m(this, "play", () => {
3366
+ const { container: t } = this.player.elements;
3367
+ this.managerPromise || this.resumeContent(), this.managerPromise.then(() => {
3368
+ this.manager.setVolume(this.player.volume), this.elements.displayContainer.initialize();
3369
+ try {
3370
+ this.initialized || (this.manager.init(t.offsetWidth, t.offsetHeight, google.ima.ViewMode.NORMAL), this.manager.start()), this.initialized = !0;
3371
+ } catch (i) {
3372
+ this.onAdError(i);
3373
+ }
3374
+ }).catch(() => {
3375
+ });
3376
+ });
3377
+ /**
3378
+ * Resume our video
3379
+ */
3380
+ m(this, "resumeContent", () => {
3381
+ this.elements.container.style.zIndex = "", this.playing = !1, F(this.player.media.play());
3382
+ });
3383
+ /**
3384
+ * Pause our video
3385
+ */
3386
+ m(this, "pauseContent", () => {
3387
+ this.elements.container.style.zIndex = 3, this.playing = !0, this.player.media.pause();
3388
+ });
3389
+ /**
3390
+ * Destroy the adsManager so we can grab new ads after this. If we don't then we're not
3391
+ * allowed to call new ads based on google policies, as they interpret this as an accidental
3392
+ * video requests. https://developers.google.com/interactive-
3393
+ * media-ads/docs/sdks/android/faq#8
3394
+ */
3395
+ m(this, "cancel", () => {
3396
+ this.initialized && this.resumeContent(), this.trigger("error"), this.loadAds();
3397
+ });
3398
+ /**
3399
+ * Re-create our adsManager
3400
+ */
3401
+ m(this, "loadAds", () => {
3402
+ this.managerPromise.then(() => {
3403
+ this.manager && this.manager.destroy(), this.managerPromise = new Promise((t) => {
3404
+ this.on("loaded", t), this.player.debug.log(this.manager);
3405
+ }), this.initialized = !1, this.requestAds();
3406
+ }).catch(() => {
3407
+ });
3408
+ });
3409
+ /**
3410
+ * Handles callbacks after an ad event was invoked
3411
+ * @param {string} event - Event type
3412
+ * @param args
3413
+ */
3414
+ m(this, "trigger", (t, ...i) => {
3415
+ const n = this.events[t];
3416
+ r.array(n) && n.forEach((s) => {
3417
+ r.function(s) && s.apply(this, i);
3418
+ });
3419
+ });
3420
+ /**
3421
+ * Add event listeners
3422
+ * @param {string} event - Event type
3423
+ * @param {Function} callback - Callback for when event occurs
3424
+ * @return {Ads}
3425
+ */
3426
+ m(this, "on", (t, i) => (r.array(this.events[t]) || (this.events[t] = []), this.events[t].push(i), this));
3427
+ /**
3428
+ * Setup a safety timer for when the ad network doesn't respond for whatever reason.
3429
+ * The advertisement has 12 seconds to get its things together. We stop this timer when the
3430
+ * advertisement is playing, or when a user action is required to start, then we clear the
3431
+ * timer on ad ready
3432
+ * @param {number} time
3433
+ * @param {string} from
3434
+ */
3435
+ m(this, "startSafetyTimer", (t, i) => {
3436
+ this.player.debug.log(`Safety timer invoked from: ${i}`), this.safetyTimer = setTimeout(() => {
3437
+ this.cancel(), this.clearSafetyTimer("startSafetyTimer()");
3438
+ }, t);
3439
+ });
3440
+ /**
3441
+ * Clear our safety timer(s)
3442
+ * @param {string} from
3443
+ */
3444
+ m(this, "clearSafetyTimer", (t) => {
3445
+ r.nullOrUndefined(this.safetyTimer) || (this.player.debug.log(`Safety timer cleared from: ${t}`), clearTimeout(this.safetyTimer), this.safetyTimer = null);
3446
+ });
3447
+ this.player = t, this.config = t.config.ads, this.playing = !1, this.initialized = !1, this.elements = {
3448
+ container: null,
3449
+ displayContainer: null
3450
+ }, this.manager = null, this.loader = null, this.cuePoints = null, this.events = {}, this.safetyTimer = null, this.countdownTimer = null, this.managerPromise = new Promise((i, n) => {
3451
+ this.on("loaded", i), this.on("error", n);
3452
+ }), this.load();
3453
+ }
3454
+ get enabled() {
3455
+ const { config: t } = this;
3456
+ return this.player.isHTML5 && this.player.isVideo && t.enabled && (!r.empty(t.publisherId) || r.url(t.tagUrl));
3457
+ }
3458
+ // Build the tag URL
3459
+ get tagUrl() {
3460
+ const { config: t } = this;
3461
+ if (r.url(t.tagUrl))
3462
+ return t.tagUrl;
3463
+ const i = {
3464
+ AV_PUBLISHERID: "58c25bb0073ef448b1087ad6",
3465
+ AV_CHANNELID: "5a0458dc28a06145e4519d21",
3466
+ AV_URL: window.location.hostname,
3467
+ cb: Date.now(),
3468
+ AV_WIDTH: 640,
3469
+ AV_HEIGHT: 480,
3470
+ AV_CDIM2: t.publisherId
3471
+ };
3472
+ return `https://go.aniview.com/api/adserver6/vast/?${ht(i)}`;
3473
+ }
3474
+ }
3475
+ function pt(e = 0, t = 0, i = 255) {
3476
+ return Math.min(Math.max(e, t), i);
3477
+ }
3478
+ function Ci(e) {
3479
+ const t = [];
3480
+ return e.split(/\r\n\r\n|\n\n|\r\r/).forEach((n) => {
3481
+ const s = {};
3482
+ n.split(/\r\n|\n|\r/).forEach((l) => {
3483
+ if (r.number(s.startTime)) {
3484
+ if (!r.empty(l.trim()) && r.empty(s.text)) {
3485
+ const o = l.trim().split("#xywh=");
3486
+ [s.text] = o, o[1] && ([s.x, s.y, s.w, s.h] = o[1].split(","));
3487
+ }
3488
+ } else {
3489
+ const o = l.match(
3490
+ /(\d{2})?:?(\d{2}):(\d{2}).(\d{2,3})( ?--> ?)(\d{2})?:?(\d{2}):(\d{2}).(\d{2,3})/
3491
+ );
3492
+ o && (s.startTime = Number(o[1] || 0) * 60 * 60 + Number(o[2]) * 60 + Number(o[3]) + +`0.${o[4]}`, s.endTime = Number(o[6] || 0) * 60 * 60 + Number(o[7]) * 60 + Number(o[8]) + +`0.${o[9]}`);
3493
+ }
3494
+ }), s.text && t.push(s);
3495
+ }), t;
3496
+ }
3497
+ function Ue(e, t) {
3498
+ const i = t.width / t.height, n = {};
3499
+ return e > i ? (n.width = t.width, n.height = 1 / e * t.width) : (n.height = t.height, n.width = e * t.height), n;
3500
+ }
3501
+ class Se {
3502
+ /**
3503
+ * PreviewThumbnails constructor.
3504
+ * @param {Plyr} player
3505
+ * @return {PreviewThumbnails}
3506
+ */
3507
+ constructor(t) {
3508
+ m(this, "load", () => {
3509
+ this.player.elements.display.seekTooltip && (this.player.elements.display.seekTooltip.hidden = this.enabled), this.enabled && this.getThumbnails().then(() => {
3510
+ this.enabled && (this.render(), this.determineContainerAutoSizing(), this.listeners(), this.loaded = !0);
3511
+ });
3512
+ });
3513
+ // Download VTT files and parse them
3514
+ m(this, "getThumbnails", () => new Promise((t) => {
3515
+ const { src: i } = this.player.config.previewThumbnails;
3516
+ if (r.empty(i))
3517
+ throw new Error("Missing previewThumbnails.src config attribute");
3518
+ const n = () => {
3519
+ this.thumbnails.sort((s, a) => s.height - a.height), this.player.debug.log("Preview thumbnails", this.thumbnails), t();
3520
+ };
3521
+ if (r.function(i))
3522
+ i((s) => {
3523
+ this.thumbnails = s, n();
3524
+ });
3525
+ else {
3526
+ const a = (r.string(i) ? [i] : i).map((l) => this.getThumbnail(l));
3527
+ Promise.all(a).then(n);
3528
+ }
3529
+ }));
3530
+ // Process individual VTT file
3531
+ m(this, "getThumbnail", (t) => new Promise((i) => {
3532
+ ne(t, void 0, this.player.config.previewThumbnails.withCredentials).then((n) => {
3533
+ const s = {
3534
+ frames: Ci(n),
3535
+ height: null,
3536
+ urlPrefix: ""
3537
+ };
3538
+ !s.frames[0].text.startsWith("/") && !s.frames[0].text.startsWith("http://") && !s.frames[0].text.startsWith("https://") && (s.urlPrefix = t.substring(0, t.lastIndexOf("/") + 1));
3539
+ const a = new Image();
3540
+ a.onload = () => {
3541
+ s.height = a.naturalHeight, s.width = a.naturalWidth, this.thumbnails.push(s), i();
3542
+ }, a.src = s.urlPrefix + s.frames[0].text;
3543
+ });
3544
+ }));
3545
+ m(this, "startMove", (t) => {
3546
+ var i, n;
3547
+ if (this.loaded && !(!r.event(t) || !["touchmove", "mousemove"].includes(t.type)) && this.player.media.duration) {
3548
+ if (t.type === "touchmove")
3549
+ this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);
3550
+ else {
3551
+ const s = this.player.elements.progress.getBoundingClientRect(), a = 100 / s.width * (t.pageX - s.left);
3552
+ this.seekTime = this.player.media.duration * (a / 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.textContent = ge(this.seekTime);
3553
+ const l = (n = (i = this.player.config.markers) == null ? void 0 : i.points) == null ? void 0 : n.find(({ time: o }) => o === Math.round(this.seekTime));
3554
+ l && this.elements.thumb.time.insertAdjacentHTML("afterbegin", `${l.label}<br>`);
3555
+ }
3556
+ this.showImageAtCurrentTime();
3557
+ }
3558
+ });
3559
+ m(this, "endMove", () => {
3560
+ this.toggleThumbContainer(!1, !0);
3561
+ });
3562
+ m(this, "startScrubbing", (t) => {
3563
+ (r.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()));
3564
+ });
3565
+ m(this, "endScrubbing", () => {
3566
+ this.mouseDown = !1, Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime) ? this.toggleScrubbingContainer(!1) : xe.call(this.player, this.player.media, "timeupdate", () => {
3567
+ this.mouseDown || this.toggleScrubbingContainer(!1);
3568
+ });
3569
+ });
3570
+ /**
3571
+ * Setup hooks for Plyr and window events
3572
+ */
3573
+ m(this, "listeners", () => {
3574
+ this.player.on("play", () => {
3575
+ this.toggleThumbContainer(!1, !0);
3576
+ }), this.player.on("seeked", () => {
3577
+ this.toggleThumbContainer(!1);
3578
+ }), this.player.on("timeupdate", () => {
3579
+ this.lastTime = this.player.media.currentTime;
3580
+ });
3581
+ });
3582
+ /**
3583
+ * Create HTML elements for image containers
3584
+ */
3585
+ m(this, "render", () => {
3586
+ this.elements.thumb.container = b("div", {
3587
+ class: this.player.config.classNames.previewThumbnails.thumbContainer
3588
+ }), this.elements.thumb.imageContainer = b("div", {
3589
+ class: this.player.config.classNames.previewThumbnails.imageContainer
3590
+ }), this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);
3591
+ const t = b("div", {
3592
+ class: this.player.config.classNames.previewThumbnails.timeContainer
3593
+ });
3594
+ this.elements.thumb.time = b("span", {}, "00:00"), t.appendChild(this.elements.thumb.time), this.elements.thumb.imageContainer.appendChild(t), r.element(this.player.elements.progress) && this.player.elements.progress.appendChild(this.elements.thumb.container), this.elements.scrubbing.container = b("div", {
3595
+ class: this.player.config.classNames.previewThumbnails.scrubbingContainer
3596
+ }), this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);
3597
+ });
3598
+ m(this, "destroy", () => {
3599
+ this.elements.thumb.container && this.elements.thumb.container.remove(), this.elements.scrubbing.container && this.elements.scrubbing.container.remove();
3600
+ });
3601
+ m(this, "showImageAtCurrentTime", () => {
3602
+ this.mouseDown ? this.setScrubbingContainerSize() : this.setThumbContainerSizeAndPos();
3603
+ const t = this.thumbnails[0].frames.findIndex(
3604
+ (s) => this.seekTime >= s.startTime && this.seekTime <= s.endTime
3605
+ ), i = t >= 0;
3606
+ let n = 0;
3607
+ this.mouseDown || this.toggleThumbContainer(i), i && (this.thumbnails.forEach((s, a) => {
3608
+ this.loadedImages.includes(s.frames[t].text) && (n = a);
3609
+ }), t !== this.showingThumb && (this.showingThumb = t, this.loadImage(n)));
3610
+ });
3611
+ // Show the image that's currently specified in this.showingThumb
3612
+ m(this, "loadImage", (t = 0) => {
3613
+ const i = this.showingThumb, n = this.thumbnails[t], { urlPrefix: s } = n, a = n.frames[i], l = n.frames[i].text, o = s + l;
3614
+ if (!this.currentImageElement || this.currentImageElement.dataset.filename !== l) {
3615
+ this.loadingImage && this.usingSprites && (this.loadingImage.onload = null);
3616
+ const c = new Image();
3617
+ c.src = o, c.dataset.index = i, c.dataset.filename = l, this.showingThumbFilename = l, this.player.debug.log(`Loading image: ${o}`), c.onload = () => this.showImage(c, a, t, i, l, !0), this.loadingImage = c, this.removeOldImages(c);
3618
+ } else
3619
+ this.showImage(this.currentImageElement, a, t, i, l, !1), this.currentImageElement.dataset.index = i, this.removeOldImages(this.currentImageElement);
3620
+ });
3621
+ m(this, "showImage", (t, i, n, s, a, l = !0) => {
3622
+ this.player.debug.log(
3623
+ `Showing thumb: ${a}. num: ${s}. qual: ${n}. newimg: ${l}`
3624
+ ), this.setImageSizeAndOffset(t, i), l && (this.currentImageContainer.appendChild(t), this.currentImageElement = t, this.loadedImages.includes(a) || this.loadedImages.push(a)), this.preloadNearby(s, !0).then(this.preloadNearby(s, !1)).then(this.getHigherQuality(n, t, i, a));
3625
+ });
3626
+ // Remove all preview images that aren't the designated current image
3627
+ m(this, "removeOldImages", (t) => {
3628
+ Array.from(this.currentImageContainer.children).forEach((i) => {
3629
+ if (i.tagName.toLowerCase() !== "img")
3630
+ return;
3631
+ const n = this.usingSprites ? 500 : 1e3;
3632
+ if (i.dataset.index !== t.dataset.index && !i.dataset.deleting) {
3633
+ i.dataset.deleting = !0;
3634
+ const { currentImageContainer: s } = this;
3635
+ setTimeout(() => {
3636
+ s.removeChild(i), this.player.debug.log(`Removing thumb: ${i.dataset.filename}`);
3637
+ }, n);
3638
+ }
3639
+ });
3640
+ });
3641
+ // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame
3642
+ // This will only preload the lowest quality
3643
+ m(this, "preloadNearby", (t, i = !0) => new Promise((n) => {
3644
+ setTimeout(() => {
3645
+ const s = this.thumbnails[0].frames[t].text;
3646
+ if (this.showingThumbFilename === s) {
3647
+ let a;
3648
+ i ? a = this.thumbnails[0].frames.slice(t) : a = this.thumbnails[0].frames.slice(0, t).reverse();
3649
+ let l = !1;
3650
+ a.forEach((o) => {
3651
+ const c = o.text;
3652
+ if (c !== s && !this.loadedImages.includes(c)) {
3653
+ l = !0, this.player.debug.log(`Preloading thumb filename: ${c}`);
3654
+ const { urlPrefix: u } = this.thumbnails[0], f = u + c, w = new Image();
3655
+ w.src = f, w.onload = () => {
3656
+ this.player.debug.log(`Preloaded thumb filename: ${c}`), this.loadedImages.includes(c) || this.loadedImages.push(c), n();
3657
+ };
3658
+ }
3659
+ }), l || n();
3660
+ }
3661
+ }, 300);
3662
+ }));
3663
+ // If user has been hovering current image for half a second, look for a higher quality one
3664
+ m(this, "getHigherQuality", (t, i, n, s) => {
3665
+ if (t < this.thumbnails.length - 1) {
3666
+ let a = i.naturalHeight;
3667
+ this.usingSprites && (a = n.h), a < this.thumbContainerHeight && setTimeout(() => {
3668
+ this.showingThumbFilename === s && (this.player.debug.log(`Showing higher quality thumb for: ${s}`), this.loadImage(t + 1));
3669
+ }, 300);
3670
+ }
3671
+ });
3672
+ m(this, "toggleThumbContainer", (t = !1, i = !1) => {
3673
+ const n = this.player.config.classNames.previewThumbnails.thumbContainerShown;
3674
+ this.elements.thumb.container.classList.toggle(n, t), !t && i && (this.showingThumb = null, this.showingThumbFilename = null);
3675
+ });
3676
+ m(this, "toggleScrubbingContainer", (t = !1) => {
3677
+ const i = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;
3678
+ this.elements.scrubbing.container.classList.toggle(i, t), t || (this.showingThumb = null, this.showingThumbFilename = null);
3679
+ });
3680
+ m(this, "determineContainerAutoSizing", () => {
3681
+ (this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) && (this.sizeSpecifiedInCSS = !0);
3682
+ });
3683
+ // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS
3684
+ m(this, "setThumbContainerSizeAndPos", () => {
3685
+ const { imageContainer: t } = this.elements.thumb;
3686
+ if (this.sizeSpecifiedInCSS) {
3687
+ if (t.clientHeight > 20 && t.clientWidth < 20) {
3688
+ const i = Math.floor(t.clientHeight * this.thumbAspectRatio);
3689
+ t.style.width = `${i}px`;
3690
+ } else if (t.clientHeight < 20 && t.clientWidth > 20) {
3691
+ const i = Math.floor(t.clientWidth / this.thumbAspectRatio);
3692
+ t.style.height = `${i}px`;
3693
+ }
3694
+ } else {
3695
+ const i = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);
3696
+ t.style.height = `${this.thumbContainerHeight}px`, t.style.width = `${i}px`;
3697
+ }
3698
+ this.setThumbContainerPos();
3699
+ });
3700
+ m(this, "setThumbContainerPos", () => {
3701
+ const t = this.player.elements.progress.getBoundingClientRect(), i = this.player.elements.container.getBoundingClientRect(), { container: n } = this.elements.thumb, s = i.left - t.left + 10, a = i.right - t.left - n.clientWidth - 10, l = this.mousePosX - t.left - n.clientWidth / 2, o = pt(l, s, a);
3702
+ n.style.left = `${o}px`, n.style.setProperty("--preview-arrow-offset", `${l - o}px`);
3703
+ });
3704
+ // Can't use 100% width, in case the video is a different aspect ratio to the video container
3705
+ m(this, "setScrubbingContainerSize", () => {
3706
+ const { width: t, height: i } = Ue(this.thumbAspectRatio, {
3707
+ width: this.player.media.clientWidth,
3708
+ height: this.player.media.clientHeight
3709
+ });
3710
+ this.elements.scrubbing.container.style.width = `${t}px`, this.elements.scrubbing.container.style.height = `${i}px`;
3711
+ });
3712
+ // Sprites need to be offset to the correct location
3713
+ m(this, "setImageSizeAndOffset", (t, i) => {
3714
+ if (!this.usingSprites) return;
3715
+ const n = this.thumbContainerHeight / i.h;
3716
+ t.style.height = `${t.naturalHeight * n}px`, t.style.width = `${t.naturalWidth * n}px`, t.style.left = `-${i.x * n}px`, t.style.top = `-${i.y * n}px`;
3717
+ });
3718
+ this.player = t, this.thumbnails = [], this.loaded = !1, this.lastMouseMoveTime = Date.now(), this.mouseDown = !1, this.loadedImages = [], this.elements = {
3719
+ thumb: {},
3720
+ scrubbing: {}
3721
+ }, this.load();
3722
+ }
3723
+ get enabled() {
3724
+ return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;
3725
+ }
3726
+ get currentImageContainer() {
3727
+ return this.mouseDown ? this.elements.scrubbing.container : this.elements.thumb.imageContainer;
3728
+ }
3729
+ get usingSprites() {
3730
+ return Object.keys(this.thumbnails[0].frames[0]).includes("w");
3731
+ }
3732
+ get thumbAspectRatio() {
3733
+ return this.usingSprites ? this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h : this.thumbnails[0].width / this.thumbnails[0].height;
3734
+ }
3735
+ get thumbContainerHeight() {
3736
+ if (this.mouseDown) {
3737
+ const { height: t } = Ue(this.thumbAspectRatio, {
3738
+ width: this.player.media.clientWidth,
3739
+ height: this.player.media.clientHeight
3740
+ });
3741
+ return t;
3742
+ }
3743
+ return this.sizeSpecifiedInCSS ? this.elements.thumb.imageContainer.clientHeight : Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);
3744
+ }
3745
+ get currentImageElement() {
3746
+ return this.mouseDown ? this.currentScrubbingImageElement : this.currentThumbnailImageElement;
3747
+ }
3748
+ set currentImageElement(t) {
3749
+ this.mouseDown ? this.currentScrubbingImageElement = t : this.currentThumbnailImageElement = t;
3750
+ }
3751
+ }
3752
+ const Pe = {
3753
+ // Add elements to HTML5 media (source, tracks, etc)
3754
+ insertElements(e, t) {
3755
+ r.string(t) ? Re(e, this.media, {
3756
+ src: t
3757
+ }) : r.array(t) && t.forEach((i) => {
3758
+ Re(e, this.media, i);
3759
+ });
3760
+ },
3761
+ // Update source
3762
+ // Sources are not checked for support so be careful
3763
+ change(e) {
3764
+ if (!tt(e, "sources.length")) {
3765
+ this.debug.warn("Invalid source format");
3766
+ return;
3767
+ }
3768
+ z.cancelRequests.call(this), this.destroy(() => {
3769
+ this.options.quality = [], U(this.media), this.media = null, r.element(this.elements.container) && this.elements.container.removeAttribute("class");
3770
+ const { sources: t, type: i } = e, [{ provider: n = W.html5, src: s }] = t, a = n === "html5" ? i : "div", l = n === "html5" ? {} : { src: s };
3771
+ Object.assign(this, {
3772
+ provider: n,
3773
+ type: i,
3774
+ // Check for support
3775
+ supported: $.check(i, n, this.config.playsinline),
3776
+ // Create new element
3777
+ media: b(a, l)
3778
+ }), this.elements.container.appendChild(this.media), r.boolean(e.autoplay) && (this.config.autoplay = e.autoplay), this.isHTML5 && (this.config.crossorigin && this.media.setAttribute("crossorigin", ""), this.config.autoplay && this.media.setAttribute("autoplay", ""), r.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", "")), S.addStyleHook.call(this), this.isHTML5 && Pe.insertElements.call(this, "source", t), this.config.title = e.title, mt.setup.call(this), this.isHTML5 && Object.keys(e).includes("tracks") && Pe.insertElements.call(this, "track", e.tracks), (this.isHTML5 || this.isEmbed && !this.supported.ui) && S.build.call(this), this.isHTML5 && this.media.load(), r.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 Se(this))), this.fullscreen.update();
3779
+ }, !0);
3780
+ }
3781
+ };
3782
+ class me {
3783
+ constructor(t, i) {
3784
+ /**
3785
+ * Play the media, or play the advertisement (if they are not blocked)
3786
+ */
3787
+ m(this, "play", () => r.function(this.media.play) ? (this.ads && this.ads.enabled && this.ads.managerPromise.then(() => this.ads.play()).catch(() => F(this.media.play())), this.media.play()) : null);
3788
+ /**
3789
+ * Pause the media
3790
+ */
3791
+ m(this, "pause", () => !this.playing || !r.function(this.media.pause) ? null : this.media.pause());
3792
+ /**
3793
+ * Toggle playback based on current status
3794
+ * @param {boolean} input
3795
+ */
3796
+ m(this, "togglePlay", (t) => (r.boolean(t) ? t : !this.playing) ? this.play() : this.pause());
3797
+ /**
3798
+ * Stop playback
3799
+ */
3800
+ m(this, "stop", () => {
3801
+ this.isHTML5 ? (this.pause(), this.restart()) : r.function(this.media.stop) && this.media.stop();
3802
+ });
3803
+ /**
3804
+ * Restart playback
3805
+ */
3806
+ m(this, "restart", () => {
3807
+ this.currentTime = 0;
3808
+ });
3809
+ /**
3810
+ * Rewind
3811
+ * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime
3812
+ */
3813
+ m(this, "rewind", (t) => {
3814
+ this.currentTime -= r.number(t) ? t : this.config.seekTime;
3815
+ });
3816
+ /**
3817
+ * Fast forward
3818
+ * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime
3819
+ */
3820
+ m(this, "forward", (t) => {
3821
+ this.currentTime += r.number(t) ? t : this.config.seekTime;
3822
+ });
3823
+ /**
3824
+ * Increase volume
3825
+ * @param {boolean} step - How much to decrease by (between 0 and 1)
3826
+ */
3827
+ m(this, "increaseVolume", (t) => {
3828
+ const i = this.media.muted ? 0 : this.volume;
3829
+ this.volume = i + (r.number(t) ? t : 0);
3830
+ });
3831
+ /**
3832
+ * Decrease volume
3833
+ * @param {boolean} step - How much to decrease by (between 0 and 1)
3834
+ */
3835
+ m(this, "decreaseVolume", (t) => {
3836
+ this.increaseVolume(-t);
3837
+ });
3838
+ /**
3839
+ * Trigger the airplay dialog
3840
+ * TODO: update player with state, support, enabled
3841
+ */
3842
+ m(this, "airplay", () => {
3843
+ $.airplay && this.media.webkitShowPlaybackTargetPicker();
3844
+ });
3845
+ /**
3846
+ * Toggle the player controls
3847
+ * @param {boolean} [toggle] - Whether to show the controls
3848
+ */
3849
+ m(this, "toggleControls", (t) => {
3850
+ if (this.supported.ui && !this.isAudio) {
3851
+ const i = he(this.elements.container, this.config.classNames.hideControls), n = typeof t > "u" ? void 0 : !t, s = E(this.elements.container, this.config.classNames.hideControls, n);
3852
+ if (s && r.array(this.config.controls) && this.config.controls.includes("settings") && !r.empty(this.config.settings) && d.toggleMenu.call(this, !1), s !== i) {
3853
+ const a = s ? "controlshidden" : "controlsshown";
3854
+ y.call(this, this.media, a);
3855
+ }
3856
+ return !s;
3857
+ }
3858
+ return !1;
3859
+ });
3860
+ /**
3861
+ * Add event listeners
3862
+ * @param {string} event - Event type
3863
+ * @param {Function} callback - Callback for when event occurs
3864
+ */
3865
+ m(this, "on", (t, i) => {
3866
+ T.call(this, this.elements.container, t, i);
3867
+ });
3868
+ /**
3869
+ * Add event listeners once
3870
+ * @param {string} event - Event type
3871
+ * @param {Function} callback - Callback for when event occurs
3872
+ */
3873
+ m(this, "once", (t, i) => {
3874
+ xe.call(this, this.elements.container, t, i);
3875
+ });
3876
+ /**
3877
+ * Remove event listeners
3878
+ * @param {string} event - Event type
3879
+ * @param {Function} callback - Callback for when event occurs
3880
+ */
3881
+ m(this, "off", (t, i) => {
3882
+ fe(this.elements.container, t, i);
3883
+ });
3884
+ /**
3885
+ * Destroy an instance
3886
+ * Event listeners are removed when elements are removed
3887
+ * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory
3888
+ * @param {Function} callback - Callback for when destroy is complete
3889
+ * @param {boolean} soft - Whether it's a soft destroy (for source changes etc)
3890
+ */
3891
+ m(this, "destroy", (t, i = !1) => {
3892
+ if (!this.ready)
3893
+ return;
3894
+ const n = () => {
3895
+ document.body.style.overflow = "", this.embed = null, i ? (Object.keys(this.elements).length && (U(this.elements.buttons.play), U(this.elements.captions), U(this.elements.controls), U(this.elements.wrapper), this.elements.buttons.play = null, this.elements.captions = null, this.elements.controls = null, this.elements.wrapper = null), r.function(t) && t()) : (Yt.call(this), z.cancelRequests.call(this), ue(this.elements.original, this.elements.container), y.call(this, this.elements.original, "destroyed", !0), r.function(t) && t.call(this.elements.original), this.ready = !1, setTimeout(() => {
3896
+ this.elements = null, this.media = null;
3897
+ }, 200));
3898
+ };
3899
+ this.stop(), clearTimeout(this.timers.loading), clearTimeout(this.timers.controls), clearTimeout(this.timers.resized), this.isHTML5 ? (S.toggleNativeControls.call(this, !0), n()) : this.isYouTube ? (clearInterval(this.timers.buffering), clearInterval(this.timers.playing), this.embed !== null && r.function(this.embed.destroy) && this.embed.destroy(), n()) : this.isVimeo && (this.embed !== null && this.embed.unload().then(n), setTimeout(n, 200));
3900
+ });
3901
+ /**
3902
+ * Check for support for a mime type (HTML5 only)
3903
+ * @param {string} type - Mime type
3904
+ */
3905
+ m(this, "supports", (t) => $.mime.call(this, t));
3906
+ if (this.timers = {}, this.ready = !1, this.loading = !1, this.failed = !1, this.touch = $.touch, this.media = t, r.string(this.media) && (this.media = document.querySelectorAll(this.media)), (window.jQuery && this.media instanceof jQuery || r.nodeList(this.media) || r.array(this.media)) && (this.media = this.media[0]), this.config = L(
3907
+ {},
3908
+ dt,
3909
+ me.defaults,
3910
+ i || {},
3911
+ (() => {
3912
+ try {
3913
+ return JSON.parse(this.media.getAttribute("data-plyr-config"));
3914
+ } catch {
3915
+ return {};
3916
+ }
3917
+ })()
3918
+ ), this.elements = {
3919
+ container: null,
3920
+ fullscreen: null,
3921
+ captions: null,
3922
+ buttons: {},
3923
+ display: {},
3924
+ progress: {},
3925
+ inputs: {},
3926
+ settings: {
3927
+ popup: null,
3928
+ menu: null,
3929
+ panels: {},
3930
+ buttons: {}
3931
+ }
3932
+ }, this.captions = {
3933
+ active: null,
3934
+ currentTrack: -1,
3935
+ meta: /* @__PURE__ */ new WeakMap()
3936
+ }, this.fullscreen = {
3937
+ active: !1
3938
+ }, this.options = {
3939
+ speed: [],
3940
+ quality: []
3941
+ }, this.debug = new hi(this.config.debug), this.debug.log("Config", this.config), this.debug.log("Support", $), r.nullOrUndefined(this.media) || !r.element(this.media)) {
3942
+ this.debug.error("Setup failed: no suitable element passed");
3943
+ return;
3944
+ }
3945
+ if (this.media.plyr) {
3946
+ this.debug.warn("Target already setup");
3947
+ return;
3948
+ }
3949
+ if (!this.config.enabled) {
3950
+ this.debug.error("Setup failed: disabled by config");
3951
+ return;
3952
+ }
3953
+ if (!$.check().api) {
3954
+ this.debug.error("Setup failed: no support");
3955
+ return;
3956
+ }
3957
+ const n = this.media.cloneNode(!0);
3958
+ n.autoplay = !1, this.elements.original = n;
3959
+ const s = this.media.tagName.toLowerCase();
3960
+ let a = null, l = null;
3961
+ switch (s) {
3962
+ case "div":
3963
+ if (a = this.media.querySelector("iframe"), r.element(a)) {
3964
+ if (l = ut(a.getAttribute("src")), this.provider = ui(l.toString()), this.elements.container = this.media, this.media = a, this.elements.container.className = "", l.search.length) {
3965
+ const o = ["1", "true"];
3966
+ o.includes(l.searchParams.get("autoplay")) && (this.config.autoplay = !0), o.includes(l.searchParams.get("loop")) && (this.config.loop.active = !0), this.isYouTube ? (this.config.playsinline = o.includes(l.searchParams.get("playsinline")), this.config.youtube.hl = l.searchParams.get("hl")) : this.config.playsinline = !0;
3967
+ }
3968
+ } else
3969
+ this.provider = this.media.getAttribute(this.config.attributes.embed.provider), this.media.removeAttribute(this.config.attributes.embed.provider);
3970
+ if (r.empty(this.provider) || !Object.values(W).includes(this.provider)) {
3971
+ this.debug.error("Setup failed: Invalid provider");
3972
+ return;
3973
+ }
3974
+ this.type = we.video;
3975
+ break;
3976
+ case "video":
3977
+ case "audio":
3978
+ this.type = s, this.provider = W.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);
3979
+ break;
3980
+ default:
3981
+ this.debug.error("Setup failed: unsupported type");
3982
+ return;
3983
+ }
3984
+ if (this.supported = $.check(this.type, this.provider), !this.supported.api) {
3985
+ this.debug.error("Setup failed: no support");
3986
+ return;
3987
+ }
3988
+ this.eventListeners = [], this.listeners = new di(this), this.storage = new te(this), this.media.plyr = this, r.element(this.elements.container) || (this.elements.container = b("div"), it(this.media, this.elements.container)), S.migrateStyles.call(this), S.addStyleHook.call(this), mt.setup.call(this), this.config.debug && T.call(this, this.elements.container, this.config.events.join(" "), (o) => {
3989
+ this.debug.log(`event: ${o.type}`);
3990
+ }), this.fullscreen = new q(this), (this.isHTML5 || this.isEmbed && !this.supported.ui) && S.build.call(this), this.listeners.container(), this.listeners.global(), this.config.ads.enabled && (this.ads = new Ti(this)), this.isHTML5 && this.config.autoplay && this.once("canplay", () => F(this.play())), this.lastSeekTime = 0, this.config.previewThumbnails.enabled && (this.previewThumbnails = new Se(this));
3991
+ }
3992
+ // ---------------------------------------
3993
+ // API
3994
+ // ---------------------------------------
3995
+ /**
3996
+ * Types and provider helpers
3997
+ */
3998
+ get isHTML5() {
3999
+ return this.provider === W.html5;
4000
+ }
4001
+ get isEmbed() {
4002
+ return this.isYouTube || this.isVimeo;
4003
+ }
4004
+ get isYouTube() {
4005
+ return this.provider === W.youtube;
4006
+ }
4007
+ get isVimeo() {
4008
+ return this.provider === W.vimeo;
4009
+ }
4010
+ get isVideo() {
4011
+ return this.type === we.video;
4012
+ }
4013
+ get isAudio() {
4014
+ return this.type === we.audio;
4015
+ }
4016
+ /**
4017
+ * Get playing state
4018
+ */
4019
+ get playing() {
4020
+ return !!(this.ready && !this.paused && !this.ended);
4021
+ }
4022
+ /**
4023
+ * Get paused state
4024
+ */
4025
+ get paused() {
4026
+ return !!this.media.paused;
4027
+ }
4028
+ /**
4029
+ * Get stopped state
4030
+ */
4031
+ get stopped() {
4032
+ return !!(this.paused && this.currentTime === 0);
4033
+ }
4034
+ /**
4035
+ * Get ended state
4036
+ */
4037
+ get ended() {
4038
+ return !!this.media.ended;
4039
+ }
4040
+ /**
4041
+ * Seek to a time
4042
+ * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)
4043
+ */
4044
+ set currentTime(t) {
4045
+ if (!this.duration)
4046
+ return;
4047
+ const i = r.number(t) && t > 0;
4048
+ this.media.currentTime = i ? Math.min(t, this.duration) : 0, this.debug.log(`Seeking to ${this.currentTime} seconds`);
4049
+ }
4050
+ /**
4051
+ * Get current time
4052
+ */
4053
+ get currentTime() {
4054
+ return Number(this.media.currentTime);
4055
+ }
4056
+ /**
4057
+ * Get buffered
4058
+ */
4059
+ get buffered() {
4060
+ const { buffered: t } = this.media;
4061
+ return r.number(t) ? t : t && t.length && this.duration > 0 ? t.end(0) / this.duration : 0;
4062
+ }
4063
+ /**
4064
+ * Get seeking status
4065
+ */
4066
+ get seeking() {
4067
+ return !!this.media.seeking;
4068
+ }
4069
+ /**
4070
+ * Get the duration of the current media
4071
+ */
4072
+ get duration() {
4073
+ const t = Number.parseFloat(this.config.duration), i = (this.media || {}).duration, n = !r.number(i) || i === 1 / 0 ? 0 : i;
4074
+ return t || n;
4075
+ }
4076
+ /**
4077
+ * Set the player volume
4078
+ * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage
4079
+ */
4080
+ set volume(t) {
4081
+ let i = t;
4082
+ const n = 1, s = 0;
4083
+ r.string(i) && (i = Number(i)), r.number(i) || (i = this.storage.get("volume")), r.number(i) || ({ volume: i } = this.config), i > n && (i = n), i < s && (i = s), this.config.volume = i, this.media.volume = i, !r.empty(t) && this.muted && i > 0 && (this.muted = !1);
4084
+ }
4085
+ /**
4086
+ * Get the current player volume
4087
+ */
4088
+ get volume() {
4089
+ return Number(this.media.volume);
4090
+ }
4091
+ /**
4092
+ * Set muted state
4093
+ * @param {boolean} mute
4094
+ */
4095
+ set muted(t) {
4096
+ let i = t;
4097
+ r.boolean(i) || (i = this.storage.get("muted")), r.boolean(i) || (i = this.config.muted), this.config.muted = i, this.media.muted = i;
4098
+ }
4099
+ /**
4100
+ * Get current muted state
4101
+ */
4102
+ get muted() {
4103
+ return !!this.media.muted;
4104
+ }
4105
+ /**
4106
+ * Check if the media has audio
4107
+ */
4108
+ get hasAudio() {
4109
+ return !this.isHTML5 || this.isAudio ? !0 : !!this.media.mozHasAudio || !!this.media.webkitAudioDecodedByteCount || !!(this.media.audioTracks && this.media.audioTracks.length);
4110
+ }
4111
+ /**
4112
+ * Set playback speed
4113
+ * @param {number} input - the speed of playback (0.5-2.0)
4114
+ */
4115
+ set speed(t) {
4116
+ let i = null;
4117
+ r.number(t) && (i = t), r.number(i) || (i = this.storage.get("speed")), r.number(i) || (i = this.config.speed.selected);
4118
+ const { minimumSpeed: n, maximumSpeed: s } = this;
4119
+ i = pt(i, n, s), this.config.speed.selected = i, setTimeout(() => {
4120
+ this.media && (this.media.playbackRate = i);
4121
+ }, 0);
4122
+ }
4123
+ /**
4124
+ * Get current playback speed
4125
+ */
4126
+ get speed() {
4127
+ return Number(this.media.playbackRate);
4128
+ }
4129
+ /**
4130
+ * Get the minimum allowed speed
4131
+ */
4132
+ get minimumSpeed() {
4133
+ return this.isYouTube ? Math.min(...this.options.speed) : this.isVimeo ? 0.5 : 0.0625;
4134
+ }
4135
+ /**
4136
+ * Get the maximum allowed speed
4137
+ */
4138
+ get maximumSpeed() {
4139
+ return this.isYouTube ? Math.max(...this.options.speed) : this.isVimeo ? 2 : 16;
4140
+ }
4141
+ /**
4142
+ * Set playback quality
4143
+ * Currently HTML5 & YouTube only
4144
+ * @param {number} input - Quality level
4145
+ */
4146
+ set quality(t) {
4147
+ const i = this.config.quality, n = this.options.quality;
4148
+ if (!n.length)
4149
+ return;
4150
+ let s = [
4151
+ !r.empty(t) && Number(t),
4152
+ this.storage.get("quality"),
4153
+ i.selected,
4154
+ i.default
4155
+ ].find(r.number), a = !0;
4156
+ if (!n.includes(s)) {
4157
+ const l = st(n, s);
4158
+ this.debug.warn(`Unsupported quality option: ${s}, using ${l} instead`), s = l, a = !1;
4159
+ }
4160
+ i.selected = s, this.media.quality = s, a && this.storage.set({ quality: s });
4161
+ }
4162
+ /**
4163
+ * Get current quality level
4164
+ */
4165
+ get quality() {
4166
+ return this.media.quality;
4167
+ }
4168
+ /**
4169
+ * Toggle loop
4170
+ * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config
4171
+ * @param {boolean} input - Whether to loop or not
4172
+ */
4173
+ set loop(t) {
4174
+ const i = r.boolean(t) ? t : this.config.loop.active;
4175
+ this.config.loop.active = i, this.media.loop = i;
4176
+ }
4177
+ /**
4178
+ * Get current loop state
4179
+ */
4180
+ get loop() {
4181
+ return !!this.media.loop;
4182
+ }
4183
+ /**
4184
+ * Set new media source
4185
+ * @param {object} input - The new source object (see docs)
4186
+ */
4187
+ set source(t) {
4188
+ Pe.change.call(this, t);
4189
+ }
4190
+ /**
4191
+ * Get current source
4192
+ */
4193
+ get source() {
4194
+ return this.media.currentSrc;
4195
+ }
4196
+ /**
4197
+ * Get a download URL (either source or custom)
4198
+ */
4199
+ get download() {
4200
+ const { download: t } = this.config.urls;
4201
+ return r.url(t) ? t : this.source;
4202
+ }
4203
+ /**
4204
+ * Set the download URL
4205
+ */
4206
+ set download(t) {
4207
+ r.url(t) && (this.config.urls.download = t, d.setDownloadUrl.call(this));
4208
+ }
4209
+ /**
4210
+ * Set the poster image for a video
4211
+ * @param {string} input - the URL for the new poster image
4212
+ */
4213
+ set poster(t) {
4214
+ if (!this.isVideo) {
4215
+ this.debug.warn("Poster can only be set for video");
4216
+ return;
4217
+ }
4218
+ S.setPoster.call(this, t, !1).catch(() => {
4219
+ });
4220
+ }
4221
+ /**
4222
+ * Get the current poster image
4223
+ */
4224
+ get poster() {
4225
+ return this.isVideo ? this.media.getAttribute("poster") || this.media.getAttribute("data-poster") : null;
4226
+ }
4227
+ /**
4228
+ * Get the current aspect ratio in use
4229
+ */
4230
+ get ratio() {
4231
+ if (!this.isVideo)
4232
+ return null;
4233
+ const t = de(Le.call(this));
4234
+ return r.array(t) ? t.join(":") : t;
4235
+ }
4236
+ /**
4237
+ * Set video aspect ratio
4238
+ */
4239
+ set ratio(t) {
4240
+ if (!this.isVideo) {
4241
+ this.debug.warn("Aspect ratio can only be set for video");
4242
+ return;
4243
+ }
4244
+ if (!r.string(t) || !rt(t)) {
4245
+ this.debug.error(`Invalid aspect ratio specified (${t})`);
4246
+ return;
4247
+ }
4248
+ this.config.ratio = de(t), X.call(this);
4249
+ }
4250
+ /**
4251
+ * Set the autoplay state
4252
+ * @param {boolean} input - Whether to autoplay or not
4253
+ */
4254
+ set autoplay(t) {
4255
+ this.config.autoplay = r.boolean(t) ? t : this.config.autoplay;
4256
+ }
4257
+ /**
4258
+ * Get the current autoplay state
4259
+ */
4260
+ get autoplay() {
4261
+ return !!this.config.autoplay;
4262
+ }
4263
+ /**
4264
+ * Toggle captions
4265
+ * @param {boolean} input - Whether to enable captions
4266
+ */
4267
+ toggleCaptions(t) {
4268
+ C.toggle.call(this, t, !1);
4269
+ }
4270
+ /**
4271
+ * Set the caption track by index
4272
+ * @param {number} input - Caption index
4273
+ */
4274
+ set currentTrack(t) {
4275
+ C.set.call(this, t, !1), C.setup.call(this);
4276
+ }
4277
+ /**
4278
+ * Get the current caption track index (-1 if disabled)
4279
+ */
4280
+ get currentTrack() {
4281
+ const { toggled: t, currentTrack: i } = this.captions;
4282
+ return t ? i : -1;
4283
+ }
4284
+ /**
4285
+ * Set the wanted language for captions
4286
+ * Since tracks can be added later it won't update the actual caption track until there is a matching track
4287
+ * @param {string} input - Two character ISO language code (e.g. EN, FR, PT, etc)
4288
+ */
4289
+ set language(t) {
4290
+ C.setLanguage.call(this, t, !1);
4291
+ }
4292
+ /**
4293
+ * Get the current track's language
4294
+ */
4295
+ get language() {
4296
+ return (C.getCurrentTrack.call(this) || {}).language;
4297
+ }
4298
+ /**
4299
+ * Toggle picture-in-picture playback on WebKit/MacOS
4300
+ * TODO: update player with state, support, enabled
4301
+ * TODO: detect outside changes
4302
+ */
4303
+ set pip(t) {
4304
+ if (!$.pip)
4305
+ return;
4306
+ const i = r.boolean(t) ? t : !this.pip;
4307
+ r.function(this.media.webkitSetPresentationMode) && this.media.webkitSetPresentationMode(i ? ye.active : ye.inactive), r.function(this.media.requestPictureInPicture) && (!this.pip && i ? this.media.requestPictureInPicture() : this.pip && !i && document.exitPictureInPicture());
4308
+ }
4309
+ /**
4310
+ * Get the current picture-in-picture state
4311
+ */
4312
+ get pip() {
4313
+ return $.pip ? r.empty(this.media.webkitPresentationMode) ? this.media === document.pictureInPictureElement : this.media.webkitPresentationMode === ye.active : null;
4314
+ }
4315
+ /**
4316
+ * Sets the preview thumbnails for the current source
4317
+ */
4318
+ setPreviewThumbnails(t) {
4319
+ this.previewThumbnails && this.previewThumbnails.loaded && (this.previewThumbnails.destroy(), this.previewThumbnails = null), Object.assign(this.config.previewThumbnails, t), this.config.previewThumbnails.enabled && (this.previewThumbnails = new Se(this));
4320
+ }
4321
+ /**
4322
+ * Check for support
4323
+ * @param {string} type - Player type (audio/video)
4324
+ * @param {string} provider - Provider (html5/youtube/vimeo)
4325
+ */
4326
+ static supported(t, i) {
4327
+ return $.check(t, i);
4328
+ }
4329
+ /**
4330
+ * Load an SVG sprite into the page
4331
+ * @param {string} url - URL for the SVG sprite
4332
+ * @param {string} [id] - Unique ID
4333
+ */
4334
+ static loadSprite(t, i) {
4335
+ return ot(t, i);
4336
+ }
4337
+ /**
4338
+ * Setup multiple instances
4339
+ * @param {*} selector
4340
+ * @param {object} options
4341
+ */
4342
+ static setup(t, i = {}) {
4343
+ let n = null;
4344
+ return r.string(t) ? n = Array.from(document.querySelectorAll(t)) : r.nodeList(t) ? n = Array.from(t) : r.array(t) && (n = t.filter(r.element)), r.empty(n) ? null : n.map((s) => new me(s, i));
4345
+ }
4346
+ }
4347
+ me.defaults = Bt(dt);
4348
+ export {
4349
+ me as default
4350
+ };