1 | function _defineProperty$1(obj, key, value) {
|
2 | key = _toPropertyKey(key);
|
3 | if (key in obj) {
|
4 | Object.defineProperty(obj, key, {
|
5 | value: value,
|
6 | enumerable: true,
|
7 | configurable: true,
|
8 | writable: true
|
9 | });
|
10 | } else {
|
11 | obj[key] = value;
|
12 | }
|
13 | return obj;
|
14 | }
|
15 | function _toPrimitive(input, hint) {
|
16 | if (typeof input !== "object" || input === null) return input;
|
17 | var prim = input[Symbol.toPrimitive];
|
18 | if (prim !== undefined) {
|
19 | var res = prim.call(input, hint || "default");
|
20 | if (typeof res !== "object") return res;
|
21 | throw new TypeError("@@toPrimitive must return a primitive value.");
|
22 | }
|
23 | return (hint === "string" ? String : Number)(input);
|
24 | }
|
25 | function _toPropertyKey(arg) {
|
26 | var key = _toPrimitive(arg, "string");
|
27 | return typeof key === "symbol" ? key : String(key);
|
28 | }
|
29 |
|
30 | function _classCallCheck(e, t) {
|
31 | if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function");
|
32 | }
|
33 | function _defineProperties(e, t) {
|
34 | for (var n = 0; n < t.length; n++) {
|
35 | var r = t[n];
|
36 | r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(e, r.key, r);
|
37 | }
|
38 | }
|
39 | function _createClass(e, t, n) {
|
40 | return t && _defineProperties(e.prototype, t), n && _defineProperties(e, n), e;
|
41 | }
|
42 | function _defineProperty(e, t, n) {
|
43 | return t in e ? Object.defineProperty(e, t, {
|
44 | value: n,
|
45 | enumerable: !0,
|
46 | configurable: !0,
|
47 | writable: !0
|
48 | }) : e[t] = n, e;
|
49 | }
|
50 | function ownKeys(e, t) {
|
51 | var n = Object.keys(e);
|
52 | if (Object.getOwnPropertySymbols) {
|
53 | var r = Object.getOwnPropertySymbols(e);
|
54 | t && (r = r.filter(function (t) {
|
55 | return Object.getOwnPropertyDescriptor(e, t).enumerable;
|
56 | })), n.push.apply(n, r);
|
57 | }
|
58 | return n;
|
59 | }
|
60 | function _objectSpread2(e) {
|
61 | for (var t = 1; t < arguments.length; t++) {
|
62 | var n = null != arguments[t] ? arguments[t] : {};
|
63 | t % 2 ? ownKeys(Object(n), !0).forEach(function (t) {
|
64 | _defineProperty(e, t, n[t]);
|
65 | }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : ownKeys(Object(n)).forEach(function (t) {
|
66 | Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t));
|
67 | });
|
68 | }
|
69 | return e;
|
70 | }
|
71 | var defaults$1 = {
|
72 | addCSS: !0,
|
73 | thumbWidth: 15,
|
74 | watch: !0
|
75 | };
|
76 | function matches$1(e, t) {
|
77 | return function () {
|
78 | return Array.from(document.querySelectorAll(t)).includes(this);
|
79 | }.call(e, t);
|
80 | }
|
81 | function trigger(e, t) {
|
82 | if (e && t) {
|
83 | var n = new Event(t, {
|
84 | bubbles: !0
|
85 | });
|
86 | e.dispatchEvent(n);
|
87 | }
|
88 | }
|
89 | var getConstructor$1 = function (e) {
|
90 | return null != e ? e.constructor : null;
|
91 | },
|
92 | instanceOf$1 = function (e, t) {
|
93 | return !!(e && t && e instanceof t);
|
94 | },
|
95 | isNullOrUndefined$1 = function (e) {
|
96 | return null == e;
|
97 | },
|
98 | isObject$1 = function (e) {
|
99 | return getConstructor$1(e) === Object;
|
100 | },
|
101 | isNumber$1 = function (e) {
|
102 | return getConstructor$1(e) === Number && !Number.isNaN(e);
|
103 | },
|
104 | isString$1 = function (e) {
|
105 | return getConstructor$1(e) === String;
|
106 | },
|
107 | isBoolean$1 = function (e) {
|
108 | return getConstructor$1(e) === Boolean;
|
109 | },
|
110 | isFunction$1 = function (e) {
|
111 | return getConstructor$1(e) === Function;
|
112 | },
|
113 | isArray$1 = function (e) {
|
114 | return Array.isArray(e);
|
115 | },
|
116 | isNodeList$1 = function (e) {
|
117 | return instanceOf$1(e, NodeList);
|
118 | },
|
119 | isElement$1 = function (e) {
|
120 | return instanceOf$1(e, Element);
|
121 | },
|
122 | isEvent$1 = function (e) {
|
123 | return instanceOf$1(e, Event);
|
124 | },
|
125 | isEmpty$1 = function (e) {
|
126 | return isNullOrUndefined$1(e) || (isString$1(e) || isArray$1(e) || isNodeList$1(e)) && !e.length || isObject$1(e) && !Object.keys(e).length;
|
127 | },
|
128 | is$1 = {
|
129 | nullOrUndefined: isNullOrUndefined$1,
|
130 | object: isObject$1,
|
131 | number: isNumber$1,
|
132 | string: isString$1,
|
133 | boolean: isBoolean$1,
|
134 | function: isFunction$1,
|
135 | array: isArray$1,
|
136 | nodeList: isNodeList$1,
|
137 | element: isElement$1,
|
138 | event: isEvent$1,
|
139 | empty: isEmpty$1
|
140 | };
|
141 | function getDecimalPlaces(e) {
|
142 | var t = "".concat(e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
|
143 | return t ? Math.max(0, (t[1] ? t[1].length : 0) - (t[2] ? +t[2] : 0)) : 0;
|
144 | }
|
145 | function round(e, t) {
|
146 | if (1 > t) {
|
147 | var n = getDecimalPlaces(t);
|
148 | return parseFloat(e.toFixed(n));
|
149 | }
|
150 | return Math.round(e / t) * t;
|
151 | }
|
152 | var RangeTouch = function () {
|
153 | function e(t, n) {
|
154 | _classCallCheck(this, e), is$1.element(t) ? this.element = t : is$1.string(t) && (this.element = document.querySelector(t)), is$1.element(this.element) && is$1.empty(this.element.rangeTouch) && (this.config = _objectSpread2({}, defaults$1, {}, n), this.init());
|
155 | }
|
156 | return _createClass(e, [{
|
157 | key: "init",
|
158 | value: function () {
|
159 | 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);
|
160 | }
|
161 | }, {
|
162 | key: "destroy",
|
163 | value: function () {
|
164 | e.enabled && (this.config.addCSS && (this.element.style.userSelect = "", this.element.style.webKitUserSelect = "", this.element.style.touchAction = ""), this.listeners(!1), this.element.rangeTouch = null);
|
165 | }
|
166 | }, {
|
167 | key: "listeners",
|
168 | value: function (e) {
|
169 | var t = this,
|
170 | n = e ? "addEventListener" : "removeEventListener";
|
171 | ["touchstart", "touchmove", "touchend"].forEach(function (e) {
|
172 | t.element[n](e, function (e) {
|
173 | return t.set(e);
|
174 | }, !1);
|
175 | });
|
176 | }
|
177 | }, {
|
178 | key: "get",
|
179 | value: function (t) {
|
180 | if (!e.enabled || !is$1.event(t)) return null;
|
181 | var n,
|
182 | r = t.target,
|
183 | i = t.changedTouches[0],
|
184 | o = parseFloat(r.getAttribute("min")) || 0,
|
185 | s = parseFloat(r.getAttribute("max")) || 100,
|
186 | u = parseFloat(r.getAttribute("step")) || 1,
|
187 | c = r.getBoundingClientRect(),
|
188 | a = 100 / c.width * (this.config.thumbWidth / 2) / 100;
|
189 | return 0 > (n = 100 / c.width * (i.clientX - c.left)) ? n = 0 : 100 < n && (n = 100), 50 > n ? n -= (100 - 2 * n) * a : 50 < n && (n += 2 * (n - 50) * a), o + round(n / 100 * (s - o), u);
|
190 | }
|
191 | }, {
|
192 | key: "set",
|
193 | value: function (t) {
|
194 | e.enabled && is$1.event(t) && !t.target.disabled && (t.preventDefault(), t.target.value = this.get(t), trigger(t.target, "touchend" === t.type ? "change" : "input"));
|
195 | }
|
196 | }], [{
|
197 | key: "setup",
|
198 | value: function (t) {
|
199 | var n = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {},
|
200 | r = null;
|
201 | if (is$1.empty(t) || is$1.string(t) ? r = Array.from(document.querySelectorAll(is$1.string(t) ? t : 'input[type="range"]')) : is$1.element(t) ? r = [t] : is$1.nodeList(t) ? r = Array.from(t) : is$1.array(t) && (r = t.filter(is$1.element)), is$1.empty(r)) return null;
|
202 | var i = _objectSpread2({}, defaults$1, {}, n);
|
203 | if (is$1.string(t) && i.watch) {
|
204 | var o = new MutationObserver(function (n) {
|
205 | Array.from(n).forEach(function (n) {
|
206 | Array.from(n.addedNodes).forEach(function (n) {
|
207 | is$1.element(n) && matches$1(n, t) && new e(n, i);
|
208 | });
|
209 | });
|
210 | });
|
211 | o.observe(document.body, {
|
212 | childList: !0,
|
213 | subtree: !0
|
214 | });
|
215 | }
|
216 | return r.map(function (t) {
|
217 | return new e(t, n);
|
218 | });
|
219 | }
|
220 | }, {
|
221 | key: "enabled",
|
222 | get: function () {
|
223 | return "ontouchstart" in document.documentElement;
|
224 | }
|
225 | }]), e;
|
226 | }();
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 | const getConstructor = input => input !== null && typeof input !== 'undefined' ? input.constructor : null;
|
233 | const instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);
|
234 | const isNullOrUndefined = input => input === null || typeof input === 'undefined';
|
235 | const isObject = input => getConstructor(input) === Object;
|
236 | const isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);
|
237 | const isString = input => getConstructor(input) === String;
|
238 | const isBoolean = input => getConstructor(input) === Boolean;
|
239 | const isFunction = input => typeof input === 'function';
|
240 | const isArray = input => Array.isArray(input);
|
241 | const isWeakMap = input => instanceOf(input, WeakMap);
|
242 | const isNodeList = input => instanceOf(input, NodeList);
|
243 | const isTextNode = input => getConstructor(input) === Text;
|
244 | const isEvent = input => instanceOf(input, Event);
|
245 | const isKeyboardEvent = input => instanceOf(input, KeyboardEvent);
|
246 | const isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
|
247 | const isTrack = input => instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind);
|
248 | const isPromise = input => instanceOf(input, Promise) && isFunction(input.then);
|
249 | const isElement = input => input !== null && typeof input === 'object' && input.nodeType === 1 && typeof input.style === 'object' && typeof input.ownerDocument === 'object';
|
250 | const isEmpty = input => isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length;
|
251 | const isUrl = input => {
|
252 |
|
253 | if (instanceOf(input, window.URL)) {
|
254 | return true;
|
255 | }
|
256 |
|
257 |
|
258 | if (!isString(input)) {
|
259 | return false;
|
260 | }
|
261 |
|
262 |
|
263 | let string = input;
|
264 | if (!input.startsWith('http://') || !input.startsWith('https://')) {
|
265 | string = `http://${input}`;
|
266 | }
|
267 | try {
|
268 | return !isEmpty(new URL(string).hostname);
|
269 | } catch (_) {
|
270 | return false;
|
271 | }
|
272 | };
|
273 | var is = {
|
274 | nullOrUndefined: isNullOrUndefined,
|
275 | object: isObject,
|
276 | number: isNumber,
|
277 | string: isString,
|
278 | boolean: isBoolean,
|
279 | function: isFunction,
|
280 | array: isArray,
|
281 | weakMap: isWeakMap,
|
282 | nodeList: isNodeList,
|
283 | element: isElement,
|
284 | textNode: isTextNode,
|
285 | event: isEvent,
|
286 | keyboardEvent: isKeyboardEvent,
|
287 | cue: isCue,
|
288 | track: isTrack,
|
289 | promise: isPromise,
|
290 | url: isUrl,
|
291 | empty: isEmpty
|
292 | };
|
293 |
|
294 | // ==========================================================================
|
295 | const transitionEndEvent = (() => {
|
296 | const element = document.createElement('span');
|
297 | const events = {
|
298 | WebkitTransition: 'webkitTransitionEnd',
|
299 | MozTransition: 'transitionend',
|
300 | OTransition: 'oTransitionEnd otransitionend',
|
301 | transition: 'transitionend'
|
302 | };
|
303 | const type = Object.keys(events).find(event => element.style[event] !== undefined);
|
304 | return is.string(type) ? events[type] : false;
|
305 | })();
|
306 |
|
307 |
|
308 | function repaint(element, delay) {
|
309 | setTimeout(() => {
|
310 | try {
|
311 |
|
312 | element.hidden = true;
|
313 |
|
314 |
|
315 | element.offsetHeight;
|
316 |
|
317 |
|
318 | element.hidden = false;
|
319 | } catch (_) {
|
320 |
|
321 | }
|
322 | }, delay);
|
323 | }
|
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
|
330 | const isIE = Boolean(window.document.documentMode);
|
331 | const isEdge = /Edge/g.test(navigator.userAgent);
|
332 | const isWebKit = 'WebkitAppearance' in document.documentElement.style && !/Edge/g.test(navigator.userAgent);
|
333 | const isIPhone = /iPhone|iPod/gi.test(navigator.userAgent) && navigator.maxTouchPoints > 1;
|
334 |
|
335 | const isIPadOS = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;
|
336 | const isIos = /iPad|iPhone|iPod/gi.test(navigator.userAgent) && navigator.maxTouchPoints > 1;
|
337 | var browser = {
|
338 | isIE,
|
339 | isEdge,
|
340 | isWebKit,
|
341 | isIPhone,
|
342 | isIPadOS,
|
343 | isIos
|
344 | };
|
345 |
|
346 |
|
347 |
|
348 |
|
349 | function cloneDeep(object) {
|
350 | return JSON.parse(JSON.stringify(object));
|
351 | }
|
352 |
|
353 |
|
354 | function getDeep(object, path) {
|
355 | return path.split('.').reduce((obj, key) => obj && obj[key], object);
|
356 | }
|
357 |
|
358 |
|
359 | function extend(target = {}, ...sources) {
|
360 | if (!sources.length) {
|
361 | return target;
|
362 | }
|
363 | const source = sources.shift();
|
364 | if (!is.object(source)) {
|
365 | return target;
|
366 | }
|
367 | Object.keys(source).forEach(key => {
|
368 | if (is.object(source[key])) {
|
369 | if (!Object.keys(target).includes(key)) {
|
370 | Object.assign(target, {
|
371 | [key]: {}
|
372 | });
|
373 | }
|
374 | extend(target[key], source[key]);
|
375 | } else {
|
376 | Object.assign(target, {
|
377 | [key]: source[key]
|
378 | });
|
379 | }
|
380 | });
|
381 | return extend(target, ...sources);
|
382 | }
|
383 |
|
384 |
|
385 |
|
386 |
|
387 | function wrap(elements, wrapper) {
|
388 |
|
389 | const targets = elements.length ? elements : [elements];
|
390 |
|
391 |
|
392 |
|
393 | Array.from(targets).reverse().forEach((element, index) => {
|
394 | const child = index > 0 ? wrapper.cloneNode(true) : wrapper;
|
395 |
|
396 | const parent = element.parentNode;
|
397 | const sibling = element.nextSibling;
|
398 |
|
399 |
|
400 |
|
401 | child.appendChild(element);
|
402 |
|
403 |
|
404 |
|
405 |
|
406 | if (sibling) {
|
407 | parent.insertBefore(child, sibling);
|
408 | } else {
|
409 | parent.appendChild(child);
|
410 | }
|
411 | });
|
412 | }
|
413 |
|
414 |
|
415 | function setAttributes(element, attributes) {
|
416 | if (!is.element(element) || is.empty(attributes)) return;
|
417 |
|
418 |
|
419 |
|
420 | Object.entries(attributes).filter(([, value]) => !is.nullOrUndefined(value)).forEach(([key, value]) => element.setAttribute(key, value));
|
421 | }
|
422 |
|
423 |
|
424 | function createElement(type, attributes, text) {
|
425 |
|
426 | const element = document.createElement(type);
|
427 |
|
428 |
|
429 | if (is.object(attributes)) {
|
430 | setAttributes(element, attributes);
|
431 | }
|
432 |
|
433 |
|
434 | if (is.string(text)) {
|
435 | element.innerText = text;
|
436 | }
|
437 |
|
438 |
|
439 | return element;
|
440 | }
|
441 |
|
442 |
|
443 | function insertAfter(element, target) {
|
444 | if (!is.element(element) || !is.element(target)) return;
|
445 | target.parentNode.insertBefore(element, target.nextSibling);
|
446 | }
|
447 |
|
448 |
|
449 | function insertElement(type, parent, attributes, text) {
|
450 | if (!is.element(parent)) return;
|
451 | parent.appendChild(createElement(type, attributes, text));
|
452 | }
|
453 |
|
454 |
|
455 | function removeElement(element) {
|
456 | if (is.nodeList(element) || is.array(element)) {
|
457 | Array.from(element).forEach(removeElement);
|
458 | return;
|
459 | }
|
460 | if (!is.element(element) || !is.element(element.parentNode)) {
|
461 | return;
|
462 | }
|
463 | element.parentNode.removeChild(element);
|
464 | }
|
465 |
|
466 |
|
467 | function emptyElement(element) {
|
468 | if (!is.element(element)) return;
|
469 | let {
|
470 | length
|
471 | } = element.childNodes;
|
472 | while (length > 0) {
|
473 | element.removeChild(element.lastChild);
|
474 | length -= 1;
|
475 | }
|
476 | }
|
477 |
|
478 |
|
479 | function replaceElement(newChild, oldChild) {
|
480 | if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) return null;
|
481 | oldChild.parentNode.replaceChild(newChild, oldChild);
|
482 | return newChild;
|
483 | }
|
484 |
|
485 |
|
486 | function getAttributesFromSelector(sel, existingAttributes) {
|
487 |
|
488 |
|
489 |
|
490 |
|
491 |
|
492 | if (!is.string(sel) || is.empty(sel)) return {};
|
493 | const attributes = {};
|
494 | const existing = extend({}, existingAttributes);
|
495 | sel.split(',').forEach(s => {
|
496 |
|
497 | const selector = s.trim();
|
498 | const className = selector.replace('.', '');
|
499 | const stripped = selector.replace(/[[\]]/g, '');
|
500 |
|
501 | const parts = stripped.split('=');
|
502 | const [key] = parts;
|
503 | const value = parts.length > 1 ? parts[1].replace(/["']/g, '') : '';
|
504 |
|
505 | const start = selector.charAt(0);
|
506 | switch (start) {
|
507 | case '.':
|
508 |
|
509 | if (is.string(existing.class)) {
|
510 | attributes.class = `${existing.class} ${className}`;
|
511 | } else {
|
512 | attributes.class = className;
|
513 | }
|
514 | break;
|
515 | case '#':
|
516 |
|
517 | attributes.id = selector.replace('#', '');
|
518 | break;
|
519 | case '[':
|
520 |
|
521 | attributes[key] = value;
|
522 | break;
|
523 | }
|
524 | });
|
525 | return extend(existing, attributes);
|
526 | }
|
527 |
|
528 |
|
529 | function toggleHidden(element, hidden) {
|
530 | if (!is.element(element)) return;
|
531 | let hide = hidden;
|
532 | if (!is.boolean(hide)) {
|
533 | hide = !element.hidden;
|
534 | }
|
535 |
|
536 |
|
537 | element.hidden = hide;
|
538 | }
|
539 |
|
540 |
|
541 | function toggleClass(element, className, force) {
|
542 | if (is.nodeList(element)) {
|
543 | return Array.from(element).map(e => toggleClass(e, className, force));
|
544 | }
|
545 | if (is.element(element)) {
|
546 | let method = 'toggle';
|
547 | if (typeof force !== 'undefined') {
|
548 | method = force ? 'add' : 'remove';
|
549 | }
|
550 | element.classList[method](className);
|
551 | return element.classList.contains(className);
|
552 | }
|
553 | return false;
|
554 | }
|
555 |
|
556 |
|
557 | function hasClass(element, className) {
|
558 | return is.element(element) && element.classList.contains(className);
|
559 | }
|
560 |
|
561 |
|
562 | function matches(element, selector) {
|
563 | const {
|
564 | prototype
|
565 | } = Element;
|
566 | function match() {
|
567 | return Array.from(document.querySelectorAll(selector)).includes(this);
|
568 | }
|
569 | const method = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;
|
570 | return method.call(element, selector);
|
571 | }
|
572 |
|
573 |
|
574 | function closest$1(element, selector) {
|
575 | const {
|
576 | prototype
|
577 | } = Element;
|
578 |
|
579 |
|
580 | function closestElement() {
|
581 | let el = this;
|
582 | do {
|
583 | if (matches.matches(el, selector)) return el;
|
584 | el = el.parentElement || el.parentNode;
|
585 | } while (el !== null && el.nodeType === 1);
|
586 | return null;
|
587 | }
|
588 | const method = prototype.closest || closestElement;
|
589 | return method.call(element, selector);
|
590 | }
|
591 |
|
592 |
|
593 | function getElements(selector) {
|
594 | return this.elements.container.querySelectorAll(selector);
|
595 | }
|
596 |
|
597 |
|
598 | function getElement(selector) {
|
599 | return this.elements.container.querySelector(selector);
|
600 | }
|
601 |
|
602 |
|
603 | function setFocus(element = null, focusVisible = false) {
|
604 | if (!is.element(element)) return;
|
605 |
|
606 |
|
607 | element.focus({
|
608 | preventScroll: true,
|
609 | focusVisible
|
610 | });
|
611 | }
|
612 |
|
613 |
|
614 |
|
615 |
|
616 | const defaultCodecs = {
|
617 | 'audio/ogg': 'vorbis',
|
618 | 'audio/wav': '1',
|
619 | 'video/webm': 'vp8, vorbis',
|
620 | 'video/mp4': 'avc1.42E01E, mp4a.40.2',
|
621 | 'video/ogg': 'theora'
|
622 | };
|
623 |
|
624 |
|
625 | const support = {
|
626 |
|
627 | audio: 'canPlayType' in document.createElement('audio'),
|
628 | video: 'canPlayType' in document.createElement('video'),
|
629 |
|
630 |
|
631 | check(type, provider) {
|
632 | const api = support[type] || provider !== 'html5';
|
633 | const ui = api && support.rangeInput;
|
634 | return {
|
635 | api,
|
636 | ui
|
637 | };
|
638 | },
|
639 |
|
640 |
|
641 | pip: (() => {
|
642 |
|
643 |
|
644 |
|
645 | if (browser.isIPhone) {
|
646 | return false;
|
647 | }
|
648 |
|
649 |
|
650 |
|
651 | if (is.function(createElement('video').webkitSetPresentationMode)) {
|
652 | return true;
|
653 | }
|
654 |
|
655 |
|
656 |
|
657 | if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {
|
658 | return true;
|
659 | }
|
660 | return false;
|
661 | })(),
|
662 |
|
663 |
|
664 | airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),
|
665 |
|
666 |
|
667 | playsinline: 'playsInline' in document.createElement('video'),
|
668 |
|
669 |
|
670 |
|
671 | mime(input) {
|
672 | if (is.empty(input)) {
|
673 | return false;
|
674 | }
|
675 | const [mediaType] = input.split('/');
|
676 | let type = input;
|
677 |
|
678 |
|
679 | if (!this.isHTML5 || mediaType !== this.type) {
|
680 | return false;
|
681 | }
|
682 |
|
683 |
|
684 | if (Object.keys(defaultCodecs).includes(type)) {
|
685 | type += `; codecs="${defaultCodecs[input]}"`;
|
686 | }
|
687 | try {
|
688 | return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));
|
689 | } catch (_) {
|
690 | return false;
|
691 | }
|
692 | },
|
693 |
|
694 | textTracks: 'textTracks' in document.createElement('video'),
|
695 |
|
696 | rangeInput: (() => {
|
697 | const range = document.createElement('input');
|
698 | range.type = 'range';
|
699 | return range.type === 'range';
|
700 | })(),
|
701 |
|
702 |
|
703 | touch: 'ontouchstart' in document.documentElement,
|
704 |
|
705 | transitions: transitionEndEvent !== false,
|
706 |
|
707 |
|
708 | reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches
|
709 | };
|
710 |
|
711 |
|
712 |
|
713 |
|
714 |
|
715 |
|
716 | const supportsPassiveListeners = (() => {
|
717 |
|
718 | let supported = false;
|
719 | try {
|
720 | const options = Object.defineProperty({}, 'passive', {
|
721 | get() {
|
722 | supported = true;
|
723 | return null;
|
724 | }
|
725 | });
|
726 | window.addEventListener('test', null, options);
|
727 | window.removeEventListener('test', null, options);
|
728 | } catch (_) {
|
729 |
|
730 | }
|
731 | return supported;
|
732 | })();
|
733 |
|
734 |
|
735 | function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {
|
736 |
|
737 | if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {
|
738 | return;
|
739 | }
|
740 |
|
741 |
|
742 | const events = event.split(' ');
|
743 |
|
744 |
|
745 | let options = capture;
|
746 |
|
747 |
|
748 | if (supportsPassiveListeners) {
|
749 | options = {
|
750 |
|
751 | passive,
|
752 |
|
753 | capture
|
754 | };
|
755 | }
|
756 |
|
757 |
|
758 | events.forEach(type => {
|
759 | if (this && this.eventListeners && toggle) {
|
760 |
|
761 | this.eventListeners.push({
|
762 | element,
|
763 | type,
|
764 | callback,
|
765 | options
|
766 | });
|
767 | }
|
768 | element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);
|
769 | });
|
770 | }
|
771 |
|
772 |
|
773 | function on(element, events = '', callback, passive = true, capture = false) {
|
774 | toggleListener.call(this, element, events, callback, true, passive, capture);
|
775 | }
|
776 |
|
777 |
|
778 | function off(element, events = '', callback, passive = true, capture = false) {
|
779 | toggleListener.call(this, element, events, callback, false, passive, capture);
|
780 | }
|
781 |
|
782 |
|
783 | function once(element, events = '', callback, passive = true, capture = false) {
|
784 | const onceCallback = (...args) => {
|
785 | off(element, events, onceCallback, passive, capture);
|
786 | callback.apply(this, args);
|
787 | };
|
788 | toggleListener.call(this, element, events, onceCallback, true, passive, capture);
|
789 | }
|
790 |
|
791 |
|
792 | function triggerEvent(element, type = '', bubbles = false, detail = {}) {
|
793 |
|
794 | if (!is.element(element) || is.empty(type)) {
|
795 | return;
|
796 | }
|
797 |
|
798 |
|
799 | const event = new CustomEvent(type, {
|
800 | bubbles,
|
801 | detail: {
|
802 | ...detail,
|
803 | plyr: this
|
804 | }
|
805 | });
|
806 |
|
807 |
|
808 | element.dispatchEvent(event);
|
809 | }
|
810 |
|
811 |
|
812 | function unbindListeners() {
|
813 | if (this && this.eventListeners) {
|
814 | this.eventListeners.forEach(item => {
|
815 | const {
|
816 | element,
|
817 | type,
|
818 | callback,
|
819 | options
|
820 | } = item;
|
821 | element.removeEventListener(type, callback, options);
|
822 | });
|
823 | this.eventListeners = [];
|
824 | }
|
825 | }
|
826 |
|
827 |
|
828 | function ready() {
|
829 | return new Promise(resolve => this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve)).then(() => {});
|
830 | }
|
831 |
|
832 |
|
833 |
|
834 |
|
835 |
|
836 |
|
837 |
|
838 | function silencePromise(value) {
|
839 | if (is.promise(value)) {
|
840 | value.then(null, () => {});
|
841 | }
|
842 | }
|
843 |
|
844 |
|
845 |
|
846 |
|
847 | function dedupe(array) {
|
848 | if (!is.array(array)) {
|
849 | return array;
|
850 | }
|
851 | return array.filter((item, index) => array.indexOf(item) === index);
|
852 | }
|
853 |
|
854 |
|
855 | function closest(array, value) {
|
856 | if (!is.array(array) || !array.length) {
|
857 | return null;
|
858 | }
|
859 | return array.reduce((prev, curr) => Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev);
|
860 | }
|
861 |
|
862 |
|
863 |
|
864 |
|
865 | function supportsCSS(declaration) {
|
866 | if (!window || !window.CSS) {
|
867 | return false;
|
868 | }
|
869 | return window.CSS.supports(declaration);
|
870 | }
|
871 |
|
872 |
|
873 | const standardRatios = [[1, 1], [4, 3], [3, 4], [5, 4], [4, 5], [3, 2], [2, 3], [16, 10], [10, 16], [16, 9], [9, 16], [21, 9], [9, 21], [32, 9], [9, 32]].reduce((out, [x, y]) => ({
|
874 | ...out,
|
875 | [x / y]: [x, y]
|
876 | }), {});
|
877 |
|
878 |
|
879 | function validateAspectRatio(input) {
|
880 | if (!is.array(input) && (!is.string(input) || !input.includes(':'))) {
|
881 | return false;
|
882 | }
|
883 | const ratio = is.array(input) ? input : input.split(':');
|
884 | return ratio.map(Number).every(is.number);
|
885 | }
|
886 |
|
887 |
|
888 | function reduceAspectRatio(ratio) {
|
889 | if (!is.array(ratio) || !ratio.every(is.number)) {
|
890 | return null;
|
891 | }
|
892 | const [width, height] = ratio;
|
893 | const getDivider = (w, h) => h === 0 ? w : getDivider(h, w % h);
|
894 | const divider = getDivider(width, height);
|
895 | return [width / divider, height / divider];
|
896 | }
|
897 |
|
898 |
|
899 | function getAspectRatio(input) {
|
900 | const parse = ratio => validateAspectRatio(ratio) ? ratio.split(':').map(Number) : null;
|
901 |
|
902 | let ratio = parse(input);
|
903 |
|
904 |
|
905 | if (ratio === null) {
|
906 | ratio = parse(this.config.ratio);
|
907 | }
|
908 |
|
909 |
|
910 | if (ratio === null && !is.empty(this.embed) && is.array(this.embed.ratio)) {
|
911 | ({
|
912 | ratio
|
913 | } = this.embed);
|
914 | }
|
915 |
|
916 |
|
917 | if (ratio === null && this.isHTML5) {
|
918 | const {
|
919 | videoWidth,
|
920 | videoHeight
|
921 | } = this.media;
|
922 | ratio = [videoWidth, videoHeight];
|
923 | }
|
924 | return reduceAspectRatio(ratio);
|
925 | }
|
926 |
|
927 |
|
928 | function setAspectRatio(input) {
|
929 | if (!this.isVideo) {
|
930 | return {};
|
931 | }
|
932 | const {
|
933 | wrapper
|
934 | } = this.elements;
|
935 | const ratio = getAspectRatio.call(this, input);
|
936 | if (!is.array(ratio)) {
|
937 | return {};
|
938 | }
|
939 | const [x, y] = reduceAspectRatio(ratio);
|
940 | const useNative = supportsCSS(`aspect-ratio: ${x}/${y}`);
|
941 | const padding = 100 / x * y;
|
942 | if (useNative) {
|
943 | wrapper.style.aspectRatio = `${x}/${y}`;
|
944 | } else {
|
945 | wrapper.style.paddingBottom = `${padding}%`;
|
946 | }
|
947 |
|
948 |
|
949 | if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
|
950 | const height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
|
951 | const offset = (height - padding) / (height / 50);
|
952 | if (this.fullscreen.active) {
|
953 | wrapper.style.paddingBottom = null;
|
954 | } else {
|
955 | this.media.style.transform = `translateY(-${offset}%)`;
|
956 | }
|
957 | } else if (this.isHTML5) {
|
958 | wrapper.classList.add(this.config.classNames.videoFixedRatio);
|
959 | }
|
960 | return {
|
961 | padding,
|
962 | ratio
|
963 | };
|
964 | }
|
965 |
|
966 |
|
967 | function roundAspectRatio(x, y, tolerance = 0.05) {
|
968 | const ratio = x / y;
|
969 | const closestRatio = closest(Object.keys(standardRatios), ratio);
|
970 |
|
971 |
|
972 | if (Math.abs(closestRatio - ratio) <= tolerance) {
|
973 | return standardRatios[closestRatio];
|
974 | }
|
975 |
|
976 |
|
977 | return [x, y];
|
978 | }
|
979 |
|
980 |
|
981 |
|
982 | function getViewportSize() {
|
983 | const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
|
984 | const height = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
|
985 | return [width, height];
|
986 | }
|
987 |
|
988 |
|
989 | const html5 = {
|
990 | getSources() {
|
991 | if (!this.isHTML5) {
|
992 | return [];
|
993 | }
|
994 | const sources = Array.from(this.media.querySelectorAll('source'));
|
995 |
|
996 |
|
997 | return sources.filter(source => {
|
998 | const type = source.getAttribute('type');
|
999 | if (is.empty(type)) {
|
1000 | return true;
|
1001 | }
|
1002 | return support.mime.call(this, type);
|
1003 | });
|
1004 | },
|
1005 |
|
1006 | getQualityOptions() {
|
1007 |
|
1008 | if (this.config.quality.forced) {
|
1009 | return this.config.quality.options;
|
1010 | }
|
1011 |
|
1012 |
|
1013 | return html5.getSources.call(this).map(source => Number(source.getAttribute('size'))).filter(Boolean);
|
1014 | },
|
1015 | setup() {
|
1016 | if (!this.isHTML5) {
|
1017 | return;
|
1018 | }
|
1019 | const player = this;
|
1020 |
|
1021 |
|
1022 | player.options.speed = player.config.speed.options;
|
1023 |
|
1024 |
|
1025 | if (!is.empty(this.config.ratio)) {
|
1026 | setAspectRatio.call(player);
|
1027 | }
|
1028 |
|
1029 |
|
1030 | Object.defineProperty(player.media, 'quality', {
|
1031 | get() {
|
1032 |
|
1033 | const sources = html5.getSources.call(player);
|
1034 | const source = sources.find(s => s.getAttribute('src') === player.source);
|
1035 |
|
1036 |
|
1037 | return source && Number(source.getAttribute('size'));
|
1038 | },
|
1039 | set(input) {
|
1040 | if (player.quality === input) {
|
1041 | return;
|
1042 | }
|
1043 |
|
1044 |
|
1045 | if (player.config.quality.forced && is.function(player.config.quality.onChange)) {
|
1046 | player.config.quality.onChange(input);
|
1047 | } else {
|
1048 |
|
1049 | const sources = html5.getSources.call(player);
|
1050 |
|
1051 | const source = sources.find(s => Number(s.getAttribute('size')) === input);
|
1052 |
|
1053 |
|
1054 | if (!source) {
|
1055 | return;
|
1056 | }
|
1057 |
|
1058 |
|
1059 | const {
|
1060 | currentTime,
|
1061 | paused,
|
1062 | preload,
|
1063 | readyState,
|
1064 | playbackRate
|
1065 | } = player.media;
|
1066 |
|
1067 |
|
1068 | player.media.src = source.getAttribute('src');
|
1069 |
|
1070 |
|
1071 | if (preload !== 'none' || readyState) {
|
1072 |
|
1073 | player.once('loadedmetadata', () => {
|
1074 | player.speed = playbackRate;
|
1075 | player.currentTime = currentTime;
|
1076 |
|
1077 |
|
1078 | if (!paused) {
|
1079 | silencePromise(player.play());
|
1080 | }
|
1081 | });
|
1082 |
|
1083 |
|
1084 | player.media.load();
|
1085 | }
|
1086 | }
|
1087 |
|
1088 |
|
1089 | triggerEvent.call(player, player.media, 'qualitychange', false, {
|
1090 | quality: input
|
1091 | });
|
1092 | }
|
1093 | });
|
1094 | },
|
1095 |
|
1096 |
|
1097 | cancelRequests() {
|
1098 | if (!this.isHTML5) {
|
1099 | return;
|
1100 | }
|
1101 |
|
1102 |
|
1103 | removeElement(html5.getSources.call(this));
|
1104 |
|
1105 |
|
1106 |
|
1107 |
|
1108 | this.media.setAttribute('src', this.config.blankVideo);
|
1109 |
|
1110 |
|
1111 |
|
1112 |
|
1113 | this.media.load();
|
1114 |
|
1115 |
|
1116 | this.debug.log('Cancelled network requests');
|
1117 | }
|
1118 | };
|
1119 |
|
1120 |
|
1121 |
|
1122 |
|
1123 | function generateId(prefix) {
|
1124 | return `${prefix}-${Math.floor(Math.random() * 10000)}`;
|
1125 | }
|
1126 |
|
1127 |
|
1128 | function format(input, ...args) {
|
1129 | if (is.empty(input)) return input;
|
1130 | return input.toString().replace(/{(\d+)}/g, (_, i) => args[i].toString());
|
1131 | }
|
1132 |
|
1133 |
|
1134 | function getPercentage(current, max) {
|
1135 | if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {
|
1136 | return 0;
|
1137 | }
|
1138 | return (current / max * 100).toFixed(2);
|
1139 | }
|
1140 |
|
1141 |
|
1142 | const replaceAll = (input = '', find = '', replace = '') => input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString());
|
1143 |
|
1144 |
|
1145 | const toTitleCase = (input = '') => input.toString().replace(/\w\S*/g, text => text.charAt(0).toUpperCase() + text.slice(1).toLowerCase());
|
1146 |
|
1147 |
|
1148 | function toPascalCase(input = '') {
|
1149 | let string = input.toString();
|
1150 |
|
1151 |
|
1152 | string = replaceAll(string, '-', ' ');
|
1153 |
|
1154 |
|
1155 | string = replaceAll(string, '_', ' ');
|
1156 |
|
1157 |
|
1158 | string = toTitleCase(string);
|
1159 |
|
1160 |
|
1161 | return replaceAll(string, ' ', '');
|
1162 | }
|
1163 |
|
1164 |
|
1165 | function toCamelCase(input = '') {
|
1166 | let string = input.toString();
|
1167 |
|
1168 |
|
1169 | string = toPascalCase(string);
|
1170 |
|
1171 |
|
1172 | return string.charAt(0).toLowerCase() + string.slice(1);
|
1173 | }
|
1174 |
|
1175 |
|
1176 | function stripHTML(source) {
|
1177 | const fragment = document.createDocumentFragment();
|
1178 | const element = document.createElement('div');
|
1179 | fragment.appendChild(element);
|
1180 | element.innerHTML = source;
|
1181 | return fragment.firstChild.innerText;
|
1182 | }
|
1183 |
|
1184 |
|
1185 | function getHTML(element) {
|
1186 | const wrapper = document.createElement('div');
|
1187 | wrapper.appendChild(element);
|
1188 | return wrapper.innerHTML;
|
1189 | }
|
1190 |
|
1191 |
|
1192 |
|
1193 |
|
1194 | const resources = {
|
1195 | pip: 'PIP',
|
1196 | airplay: 'AirPlay',
|
1197 | html5: 'HTML5',
|
1198 | vimeo: 'Vimeo',
|
1199 | youtube: 'YouTube'
|
1200 | };
|
1201 | const i18n = {
|
1202 | get(key = '', config = {}) {
|
1203 | if (is.empty(key) || is.empty(config)) {
|
1204 | return '';
|
1205 | }
|
1206 | let string = getDeep(config.i18n, key);
|
1207 | if (is.empty(string)) {
|
1208 | if (Object.keys(resources).includes(key)) {
|
1209 | return resources[key];
|
1210 | }
|
1211 | return '';
|
1212 | }
|
1213 | const replace = {
|
1214 | '{seektime}': config.seekTime,
|
1215 | '{title}': config.title
|
1216 | };
|
1217 | Object.entries(replace).forEach(([k, v]) => {
|
1218 | string = replaceAll(string, k, v);
|
1219 | });
|
1220 | return string;
|
1221 | }
|
1222 | };
|
1223 |
|
1224 | class Storage {
|
1225 | constructor(player) {
|
1226 | _defineProperty$1(this, "get", key => {
|
1227 | if (!Storage.supported || !this.enabled) {
|
1228 | return null;
|
1229 | }
|
1230 | const store = window.localStorage.getItem(this.key);
|
1231 | if (is.empty(store)) {
|
1232 | return null;
|
1233 | }
|
1234 | const json = JSON.parse(store);
|
1235 | return is.string(key) && key.length ? json[key] : json;
|
1236 | });
|
1237 | _defineProperty$1(this, "set", object => {
|
1238 |
|
1239 | if (!Storage.supported || !this.enabled) {
|
1240 | return;
|
1241 | }
|
1242 |
|
1243 |
|
1244 | if (!is.object(object)) {
|
1245 | return;
|
1246 | }
|
1247 |
|
1248 |
|
1249 | let storage = this.get();
|
1250 |
|
1251 |
|
1252 | if (is.empty(storage)) {
|
1253 | storage = {};
|
1254 | }
|
1255 |
|
1256 |
|
1257 | extend(storage, object);
|
1258 |
|
1259 |
|
1260 | try {
|
1261 | window.localStorage.setItem(this.key, JSON.stringify(storage));
|
1262 | } catch (_) {
|
1263 |
|
1264 | }
|
1265 | });
|
1266 | this.enabled = player.config.storage.enabled;
|
1267 | this.key = player.config.storage.key;
|
1268 | }
|
1269 |
|
1270 |
|
1271 | static get supported() {
|
1272 | try {
|
1273 | if (!('localStorage' in window)) {
|
1274 | return false;
|
1275 | }
|
1276 | const test = '___test';
|
1277 |
|
1278 |
|
1279 |
|
1280 | window.localStorage.setItem(test, test);
|
1281 | window.localStorage.removeItem(test);
|
1282 | return true;
|
1283 | } catch (_) {
|
1284 | return false;
|
1285 | }
|
1286 | }
|
1287 | }
|
1288 |
|
1289 |
|
1290 |
|
1291 |
|
1292 |
|
1293 |
|
1294 | function fetch(url, responseType = 'text') {
|
1295 | return new Promise((resolve, reject) => {
|
1296 | try {
|
1297 | const request = new XMLHttpRequest();
|
1298 |
|
1299 |
|
1300 | if (!('withCredentials' in request)) {
|
1301 | return;
|
1302 | }
|
1303 | request.addEventListener('load', () => {
|
1304 | if (responseType === 'text') {
|
1305 | try {
|
1306 | resolve(JSON.parse(request.responseText));
|
1307 | } catch (_) {
|
1308 | resolve(request.responseText);
|
1309 | }
|
1310 | } else {
|
1311 | resolve(request.response);
|
1312 | }
|
1313 | });
|
1314 | request.addEventListener('error', () => {
|
1315 | throw new Error(request.status);
|
1316 | });
|
1317 | request.open('GET', url, true);
|
1318 |
|
1319 |
|
1320 | request.responseType = responseType;
|
1321 | request.send();
|
1322 | } catch (error) {
|
1323 | reject(error);
|
1324 | }
|
1325 | });
|
1326 | }
|
1327 |
|
1328 |
|
1329 |
|
1330 |
|
1331 | function loadSprite(url, id) {
|
1332 | if (!is.string(url)) {
|
1333 | return;
|
1334 | }
|
1335 | const prefix = 'cache';
|
1336 | const hasId = is.string(id);
|
1337 | let isCached = false;
|
1338 | const exists = () => document.getElementById(id) !== null;
|
1339 | const update = (container, data) => {
|
1340 |
|
1341 | container.innerHTML = data;
|
1342 |
|
1343 |
|
1344 | if (hasId && exists()) {
|
1345 | return;
|
1346 | }
|
1347 |
|
1348 |
|
1349 | document.body.insertAdjacentElement('afterbegin', container);
|
1350 | };
|
1351 |
|
1352 |
|
1353 | if (!hasId || !exists()) {
|
1354 | const useStorage = Storage.supported;
|
1355 |
|
1356 | const container = document.createElement('div');
|
1357 | container.setAttribute('hidden', '');
|
1358 | if (hasId) {
|
1359 | container.setAttribute('id', id);
|
1360 | }
|
1361 |
|
1362 |
|
1363 | if (useStorage) {
|
1364 | const cached = window.localStorage.getItem(`${prefix}-${id}`);
|
1365 | isCached = cached !== null;
|
1366 | if (isCached) {
|
1367 | const data = JSON.parse(cached);
|
1368 | update(container, data.content);
|
1369 | }
|
1370 | }
|
1371 |
|
1372 |
|
1373 | fetch(url).then(result => {
|
1374 | if (is.empty(result)) {
|
1375 | return;
|
1376 | }
|
1377 | if (useStorage) {
|
1378 | try {
|
1379 | window.localStorage.setItem(`${prefix}-${id}`, JSON.stringify({
|
1380 | content: result
|
1381 | }));
|
1382 | } catch (_) {
|
1383 |
|
1384 | }
|
1385 | }
|
1386 | update(container, result);
|
1387 | }).catch(() => {});
|
1388 | }
|
1389 | }
|
1390 |
|
1391 |
|
1392 |
|
1393 |
|
1394 | const getHours = value => Math.trunc(value / 60 / 60 % 60, 10);
|
1395 | const getMinutes = value => Math.trunc(value / 60 % 60, 10);
|
1396 | const getSeconds = value => Math.trunc(value % 60, 10);
|
1397 |
|
1398 |
|
1399 | function formatTime(time = 0, displayHours = false, inverted = false) {
|
1400 |
|
1401 | if (!is.number(time)) {
|
1402 | return formatTime(undefined, displayHours, inverted);
|
1403 | }
|
1404 |
|
1405 |
|
1406 | const format = value => `0${value}`.slice(-2);
|
1407 |
|
1408 | let hours = getHours(time);
|
1409 | const mins = getMinutes(time);
|
1410 | const secs = getSeconds(time);
|
1411 |
|
1412 |
|
1413 | if (displayHours || hours > 0) {
|
1414 | hours = `${hours}:`;
|
1415 | } else {
|
1416 | hours = '';
|
1417 | }
|
1418 |
|
1419 |
|
1420 | return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;
|
1421 | }
|
1422 |
|
1423 |
|
1424 |
|
1425 |
|
1426 | const controls = {
|
1427 |
|
1428 | getIconUrl() {
|
1429 | const url = new URL(this.config.iconUrl, window.location);
|
1430 | const host = window.location.host ? window.location.host : window.top.location.host;
|
1431 | const cors = url.host !== host || browser.isIE && !window.svg4everybody;
|
1432 | return {
|
1433 | url: this.config.iconUrl,
|
1434 | cors
|
1435 | };
|
1436 | },
|
1437 |
|
1438 | findElements() {
|
1439 | try {
|
1440 | this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);
|
1441 |
|
1442 |
|
1443 | this.elements.buttons = {
|
1444 | play: getElements.call(this, this.config.selectors.buttons.play),
|
1445 | pause: getElement.call(this, this.config.selectors.buttons.pause),
|
1446 | restart: getElement.call(this, this.config.selectors.buttons.restart),
|
1447 | rewind: getElement.call(this, this.config.selectors.buttons.rewind),
|
1448 | fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),
|
1449 | mute: getElement.call(this, this.config.selectors.buttons.mute),
|
1450 | pip: getElement.call(this, this.config.selectors.buttons.pip),
|
1451 | airplay: getElement.call(this, this.config.selectors.buttons.airplay),
|
1452 | settings: getElement.call(this, this.config.selectors.buttons.settings),
|
1453 | captions: getElement.call(this, this.config.selectors.buttons.captions),
|
1454 | fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen)
|
1455 | };
|
1456 |
|
1457 |
|
1458 | this.elements.progress = getElement.call(this, this.config.selectors.progress);
|
1459 |
|
1460 |
|
1461 | this.elements.inputs = {
|
1462 | seek: getElement.call(this, this.config.selectors.inputs.seek),
|
1463 | volume: getElement.call(this, this.config.selectors.inputs.volume)
|
1464 | };
|
1465 |
|
1466 |
|
1467 | this.elements.display = {
|
1468 | buffer: getElement.call(this, this.config.selectors.display.buffer),
|
1469 | currentTime: getElement.call(this, this.config.selectors.display.currentTime),
|
1470 | duration: getElement.call(this, this.config.selectors.display.duration)
|
1471 | };
|
1472 |
|
1473 |
|
1474 | if (is.element(this.elements.progress)) {
|
1475 | this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);
|
1476 | }
|
1477 | return true;
|
1478 | } catch (error) {
|
1479 |
|
1480 | this.debug.warn('It looks like there is a problem with your custom controls HTML', error);
|
1481 |
|
1482 |
|
1483 | this.toggleNativeControls(true);
|
1484 | return false;
|
1485 | }
|
1486 | },
|
1487 |
|
1488 | createIcon(type, attributes) {
|
1489 | const namespace = 'http://www.w3.org/2000/svg';
|
1490 | const iconUrl = controls.getIconUrl.call(this);
|
1491 | const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;
|
1492 |
|
1493 | const icon = document.createElementNS(namespace, 'svg');
|
1494 | setAttributes(icon, extend(attributes, {
|
1495 | 'aria-hidden': 'true',
|
1496 | focusable: 'false'
|
1497 | }));
|
1498 |
|
1499 |
|
1500 | const use = document.createElementNS(namespace, 'use');
|
1501 | const path = `${iconPath}-${type}`;
|
1502 |
|
1503 |
|
1504 |
|
1505 |
|
1506 | if ('href' in use) {
|
1507 | use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);
|
1508 | }
|
1509 |
|
1510 |
|
1511 | use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);
|
1512 |
|
1513 |
|
1514 | icon.appendChild(use);
|
1515 | return icon;
|
1516 | },
|
1517 |
|
1518 | createLabel(key, attr = {}) {
|
1519 | const text = i18n.get(key, this.config);
|
1520 | const attributes = {
|
1521 | ...attr,
|
1522 | class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ')
|
1523 | };
|
1524 | return createElement('span', attributes, text);
|
1525 | },
|
1526 |
|
1527 | createBadge(text) {
|
1528 | if (is.empty(text)) {
|
1529 | return null;
|
1530 | }
|
1531 | const badge = createElement('span', {
|
1532 | class: this.config.classNames.menu.value
|
1533 | });
|
1534 | badge.appendChild(createElement('span', {
|
1535 | class: this.config.classNames.menu.badge
|
1536 | }, text));
|
1537 | return badge;
|
1538 | },
|
1539 |
|
1540 | createButton(buttonType, attr) {
|
1541 | const attributes = extend({}, attr);
|
1542 | let type = toCamelCase(buttonType);
|
1543 | const props = {
|
1544 | element: 'button',
|
1545 | toggle: false,
|
1546 | label: null,
|
1547 | icon: null,
|
1548 | labelPressed: null,
|
1549 | iconPressed: null
|
1550 | };
|
1551 | ['element', 'icon', 'label'].forEach(key => {
|
1552 | if (Object.keys(attributes).includes(key)) {
|
1553 | props[key] = attributes[key];
|
1554 | delete attributes[key];
|
1555 | }
|
1556 | });
|
1557 |
|
1558 |
|
1559 | if (props.element === 'button' && !Object.keys(attributes).includes('type')) {
|
1560 | attributes.type = 'button';
|
1561 | }
|
1562 |
|
1563 |
|
1564 | if (Object.keys(attributes).includes('class')) {
|
1565 | if (!attributes.class.split(' ').some(c => c === this.config.classNames.control)) {
|
1566 | extend(attributes, {
|
1567 | class: `${attributes.class} ${this.config.classNames.control}`
|
1568 | });
|
1569 | }
|
1570 | } else {
|
1571 | attributes.class = this.config.classNames.control;
|
1572 | }
|
1573 |
|
1574 |
|
1575 | switch (buttonType) {
|
1576 | case 'play':
|
1577 | props.toggle = true;
|
1578 | props.label = 'play';
|
1579 | props.labelPressed = 'pause';
|
1580 | props.icon = 'play';
|
1581 | props.iconPressed = 'pause';
|
1582 | break;
|
1583 | case 'mute':
|
1584 | props.toggle = true;
|
1585 | props.label = 'mute';
|
1586 | props.labelPressed = 'unmute';
|
1587 | props.icon = 'volume';
|
1588 | props.iconPressed = 'muted';
|
1589 | break;
|
1590 | case 'captions':
|
1591 | props.toggle = true;
|
1592 | props.label = 'enableCaptions';
|
1593 | props.labelPressed = 'disableCaptions';
|
1594 | props.icon = 'captions-off';
|
1595 | props.iconPressed = 'captions-on';
|
1596 | break;
|
1597 | case 'fullscreen':
|
1598 | props.toggle = true;
|
1599 | props.label = 'enterFullscreen';
|
1600 | props.labelPressed = 'exitFullscreen';
|
1601 | props.icon = 'enter-fullscreen';
|
1602 | props.iconPressed = 'exit-fullscreen';
|
1603 | break;
|
1604 | case 'play-large':
|
1605 | attributes.class += ` ${this.config.classNames.control}--overlaid`;
|
1606 | type = 'play';
|
1607 | props.label = 'play';
|
1608 | props.icon = 'play';
|
1609 | break;
|
1610 | default:
|
1611 | if (is.empty(props.label)) {
|
1612 | props.label = type;
|
1613 | }
|
1614 | if (is.empty(props.icon)) {
|
1615 | props.icon = buttonType;
|
1616 | }
|
1617 | }
|
1618 | const button = createElement(props.element);
|
1619 |
|
1620 |
|
1621 | if (props.toggle) {
|
1622 |
|
1623 | button.appendChild(controls.createIcon.call(this, props.iconPressed, {
|
1624 | class: 'icon--pressed'
|
1625 | }));
|
1626 | button.appendChild(controls.createIcon.call(this, props.icon, {
|
1627 | class: 'icon--not-pressed'
|
1628 | }));
|
1629 |
|
1630 |
|
1631 | button.appendChild(controls.createLabel.call(this, props.labelPressed, {
|
1632 | class: 'label--pressed'
|
1633 | }));
|
1634 | button.appendChild(controls.createLabel.call(this, props.label, {
|
1635 | class: 'label--not-pressed'
|
1636 | }));
|
1637 | } else {
|
1638 | button.appendChild(controls.createIcon.call(this, props.icon));
|
1639 | button.appendChild(controls.createLabel.call(this, props.label));
|
1640 | }
|
1641 |
|
1642 |
|
1643 | extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));
|
1644 | setAttributes(button, attributes);
|
1645 |
|
1646 |
|
1647 | if (type === 'play') {
|
1648 | if (!is.array(this.elements.buttons[type])) {
|
1649 | this.elements.buttons[type] = [];
|
1650 | }
|
1651 | this.elements.buttons[type].push(button);
|
1652 | } else {
|
1653 | this.elements.buttons[type] = button;
|
1654 | }
|
1655 | return button;
|
1656 | },
|
1657 |
|
1658 | createRange(type, attributes) {
|
1659 |
|
1660 | const input = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
1661 | type: 'range',
|
1662 | min: 0,
|
1663 | max: 100,
|
1664 | step: 0.01,
|
1665 | value: 0,
|
1666 | autocomplete: 'off',
|
1667 |
|
1668 | role: 'slider',
|
1669 | 'aria-label': i18n.get(type, this.config),
|
1670 | 'aria-valuemin': 0,
|
1671 | 'aria-valuemax': 100,
|
1672 | 'aria-valuenow': 0
|
1673 | }, attributes));
|
1674 | this.elements.inputs[type] = input;
|
1675 |
|
1676 |
|
1677 | controls.updateRangeFill.call(this, input);
|
1678 |
|
1679 |
|
1680 | RangeTouch.setup(input);
|
1681 | return input;
|
1682 | },
|
1683 |
|
1684 | createProgress(type, attributes) {
|
1685 | const progress = createElement('progress', extend(getAttributesFromSelector(this.config.selectors.display[type]), {
|
1686 | min: 0,
|
1687 | max: 100,
|
1688 | value: 0,
|
1689 | role: 'progressbar',
|
1690 | 'aria-hidden': true
|
1691 | }, attributes));
|
1692 |
|
1693 |
|
1694 | if (type !== 'volume') {
|
1695 | progress.appendChild(createElement('span', null, '0'));
|
1696 | const suffixKey = {
|
1697 | played: 'played',
|
1698 | buffer: 'buffered'
|
1699 | }[type];
|
1700 | const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';
|
1701 | progress.innerText = `% ${suffix.toLowerCase()}`;
|
1702 | }
|
1703 | this.elements.display[type] = progress;
|
1704 | return progress;
|
1705 | },
|
1706 |
|
1707 | createTime(type, attrs) {
|
1708 | const attributes = getAttributesFromSelector(this.config.selectors.display[type], attrs);
|
1709 | const container = createElement('div', extend(attributes, {
|
1710 | class: `${attributes.class ? attributes.class : ''} ${this.config.classNames.display.time} `.trim(),
|
1711 | 'aria-label': i18n.get(type, this.config),
|
1712 | role: 'timer'
|
1713 | }), '00:00');
|
1714 |
|
1715 |
|
1716 | this.elements.display[type] = container;
|
1717 | return container;
|
1718 | },
|
1719 |
|
1720 |
|
1721 |
|
1722 | bindMenuItemShortcuts(menuItem, type) {
|
1723 |
|
1724 | on.call(this, menuItem, 'keydown keyup', event => {
|
1725 |
|
1726 | if (![' ', 'ArrowUp', 'ArrowDown', 'ArrowRight'].includes(event.key)) {
|
1727 | return;
|
1728 | }
|
1729 |
|
1730 |
|
1731 | event.preventDefault();
|
1732 | event.stopPropagation();
|
1733 |
|
1734 |
|
1735 | if (event.type === 'keydown') {
|
1736 | return;
|
1737 | }
|
1738 | const isRadioButton = matches(menuItem, '[role="menuitemradio"]');
|
1739 |
|
1740 |
|
1741 | if (!isRadioButton && [' ', 'ArrowRight'].includes(event.key)) {
|
1742 | controls.showMenuPanel.call(this, type, true);
|
1743 | } else {
|
1744 | let target;
|
1745 | if (event.key !== ' ') {
|
1746 | if (event.key === 'ArrowDown' || isRadioButton && event.key === 'ArrowRight') {
|
1747 | target = menuItem.nextElementSibling;
|
1748 | if (!is.element(target)) {
|
1749 | target = menuItem.parentNode.firstElementChild;
|
1750 | }
|
1751 | } else {
|
1752 | target = menuItem.previousElementSibling;
|
1753 | if (!is.element(target)) {
|
1754 | target = menuItem.parentNode.lastElementChild;
|
1755 | }
|
1756 | }
|
1757 | setFocus.call(this, target, true);
|
1758 | }
|
1759 | }
|
1760 | }, false);
|
1761 |
|
1762 |
|
1763 |
|
1764 | on.call(this, menuItem, 'keyup', event => {
|
1765 | if (event.key !== 'Return') return;
|
1766 | controls.focusFirstMenuItem.call(this, null, true);
|
1767 | });
|
1768 | },
|
1769 |
|
1770 | createMenuItem({
|
1771 | value,
|
1772 | list,
|
1773 | type,
|
1774 | title,
|
1775 | badge = null,
|
1776 | checked = false
|
1777 | }) {
|
1778 | const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);
|
1779 | const menuItem = createElement('button', extend(attributes, {
|
1780 | type: 'button',
|
1781 | role: 'menuitemradio',
|
1782 | class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),
|
1783 | 'aria-checked': checked,
|
1784 | value
|
1785 | }));
|
1786 | const flex = createElement('span');
|
1787 |
|
1788 |
|
1789 | flex.innerHTML = title;
|
1790 | if (is.element(badge)) {
|
1791 | flex.appendChild(badge);
|
1792 | }
|
1793 | menuItem.appendChild(flex);
|
1794 |
|
1795 |
|
1796 | Object.defineProperty(menuItem, 'checked', {
|
1797 | enumerable: true,
|
1798 | get() {
|
1799 | return menuItem.getAttribute('aria-checked') === 'true';
|
1800 | },
|
1801 | set(check) {
|
1802 |
|
1803 | if (check) {
|
1804 | Array.from(menuItem.parentNode.children).filter(node => matches(node, '[role="menuitemradio"]')).forEach(node => node.setAttribute('aria-checked', 'false'));
|
1805 | }
|
1806 | menuItem.setAttribute('aria-checked', check ? 'true' : 'false');
|
1807 | }
|
1808 | });
|
1809 | this.listeners.bind(menuItem, 'click keyup', event => {
|
1810 | if (is.keyboardEvent(event) && event.key !== ' ') {
|
1811 | return;
|
1812 | }
|
1813 | event.preventDefault();
|
1814 | event.stopPropagation();
|
1815 | menuItem.checked = true;
|
1816 | switch (type) {
|
1817 | case 'language':
|
1818 | this.currentTrack = Number(value);
|
1819 | break;
|
1820 | case 'quality':
|
1821 | this.quality = value;
|
1822 | break;
|
1823 | case 'speed':
|
1824 | this.speed = parseFloat(value);
|
1825 | break;
|
1826 | }
|
1827 | controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));
|
1828 | }, type, false);
|
1829 | controls.bindMenuItemShortcuts.call(this, menuItem, type);
|
1830 | list.appendChild(menuItem);
|
1831 | },
|
1832 |
|
1833 | formatTime(time = 0, inverted = false) {
|
1834 |
|
1835 | if (!is.number(time)) {
|
1836 | return time;
|
1837 | }
|
1838 |
|
1839 |
|
1840 | const forceHours = getHours(this.duration) > 0;
|
1841 | return formatTime(time, forceHours, inverted);
|
1842 | },
|
1843 |
|
1844 | updateTimeDisplay(target = null, time = 0, inverted = false) {
|
1845 |
|
1846 | if (!is.element(target) || !is.number(time)) {
|
1847 | return;
|
1848 | }
|
1849 |
|
1850 |
|
1851 | target.innerText = controls.formatTime(time, inverted);
|
1852 | },
|
1853 |
|
1854 | updateVolume() {
|
1855 | if (!this.supported.ui) {
|
1856 | return;
|
1857 | }
|
1858 |
|
1859 |
|
1860 | if (is.element(this.elements.inputs.volume)) {
|
1861 | controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);
|
1862 | }
|
1863 |
|
1864 |
|
1865 | if (is.element(this.elements.buttons.mute)) {
|
1866 | this.elements.buttons.mute.pressed = this.muted || this.volume === 0;
|
1867 | }
|
1868 | },
|
1869 |
|
1870 | setRange(target, value = 0) {
|
1871 | if (!is.element(target)) {
|
1872 | return;
|
1873 | }
|
1874 |
|
1875 |
|
1876 | target.value = value;
|
1877 |
|
1878 |
|
1879 | controls.updateRangeFill.call(this, target);
|
1880 | },
|
1881 |
|
1882 | updateProgress(event) {
|
1883 | if (!this.supported.ui || !is.event(event)) {
|
1884 | return;
|
1885 | }
|
1886 | let value = 0;
|
1887 | const setProgress = (target, input) => {
|
1888 | const val = is.number(input) ? input : 0;
|
1889 | const progress = is.element(target) ? target : this.elements.display.buffer;
|
1890 |
|
1891 |
|
1892 | if (is.element(progress)) {
|
1893 | progress.value = val;
|
1894 |
|
1895 |
|
1896 | const label = progress.getElementsByTagName('span')[0];
|
1897 | if (is.element(label)) {
|
1898 | label.childNodes[0].nodeValue = val;
|
1899 | }
|
1900 | }
|
1901 | };
|
1902 | if (event) {
|
1903 | switch (event.type) {
|
1904 |
|
1905 | case 'timeupdate':
|
1906 | case 'seeking':
|
1907 | case 'seeked':
|
1908 | value = getPercentage(this.currentTime, this.duration);
|
1909 |
|
1910 |
|
1911 | if (event.type === 'timeupdate') {
|
1912 | controls.setRange.call(this, this.elements.inputs.seek, value);
|
1913 | }
|
1914 | break;
|
1915 |
|
1916 |
|
1917 | case 'playing':
|
1918 | case 'progress':
|
1919 | setProgress(this.elements.display.buffer, this.buffered * 100);
|
1920 | break;
|
1921 | }
|
1922 | }
|
1923 | },
|
1924 |
|
1925 | updateRangeFill(target) {
|
1926 |
|
1927 | const range = is.event(target) ? target.target : target;
|
1928 |
|
1929 |
|
1930 | if (!is.element(range) || range.getAttribute('type') !== 'range') {
|
1931 | return;
|
1932 | }
|
1933 |
|
1934 |
|
1935 | if (matches(range, this.config.selectors.inputs.seek)) {
|
1936 | range.setAttribute('aria-valuenow', this.currentTime);
|
1937 | const currentTime = controls.formatTime(this.currentTime);
|
1938 | const duration = controls.formatTime(this.duration);
|
1939 | const format = i18n.get('seekLabel', this.config);
|
1940 | range.setAttribute('aria-valuetext', format.replace('{currentTime}', currentTime).replace('{duration}', duration));
|
1941 | } else if (matches(range, this.config.selectors.inputs.volume)) {
|
1942 | const percent = range.value * 100;
|
1943 | range.setAttribute('aria-valuenow', percent);
|
1944 | range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);
|
1945 | } else {
|
1946 | range.setAttribute('aria-valuenow', range.value);
|
1947 | }
|
1948 |
|
1949 |
|
1950 | if (!browser.isWebKit && !browser.isIPadOS) {
|
1951 | return;
|
1952 | }
|
1953 |
|
1954 |
|
1955 | range.style.setProperty('--value', `${range.value / range.max * 100}%`);
|
1956 | },
|
1957 |
|
1958 | updateSeekTooltip(event) {
|
1959 | var _this$config$markers, _this$config$markers$;
|
1960 |
|
1961 | if (!this.config.tooltips.seek || !is.element(this.elements.inputs.seek) || !is.element(this.elements.display.seekTooltip) || this.duration === 0) {
|
1962 | return;
|
1963 | }
|
1964 | const tipElement = this.elements.display.seekTooltip;
|
1965 | const visible = `${this.config.classNames.tooltip}--visible`;
|
1966 | const toggle = show => toggleClass(tipElement, visible, show);
|
1967 |
|
1968 |
|
1969 | if (this.touch) {
|
1970 | toggle(false);
|
1971 | return;
|
1972 | }
|
1973 |
|
1974 |
|
1975 | let percent = 0;
|
1976 | const clientRect = this.elements.progress.getBoundingClientRect();
|
1977 | if (is.event(event)) {
|
1978 | percent = 100 / clientRect.width * (event.pageX - clientRect.left);
|
1979 | } else if (hasClass(tipElement, visible)) {
|
1980 | percent = parseFloat(tipElement.style.left, 10);
|
1981 | } else {
|
1982 | return;
|
1983 | }
|
1984 |
|
1985 |
|
1986 | if (percent < 0) {
|
1987 | percent = 0;
|
1988 | } else if (percent > 100) {
|
1989 | percent = 100;
|
1990 | }
|
1991 | const time = this.duration / 100 * percent;
|
1992 |
|
1993 |
|
1994 | tipElement.innerText = controls.formatTime(time);
|
1995 |
|
1996 |
|
1997 | const point = (_this$config$markers = this.config.markers) === null || _this$config$markers === void 0 ? void 0 : (_this$config$markers$ = _this$config$markers.points) === null || _this$config$markers$ === void 0 ? void 0 : _this$config$markers$.find(({
|
1998 | time: t
|
1999 | }) => t === Math.round(time));
|
2000 |
|
2001 |
|
2002 | if (point) {
|
2003 | tipElement.insertAdjacentHTML('afterbegin', `${point.label}<br>`);
|
2004 | }
|
2005 |
|
2006 |
|
2007 | tipElement.style.left = `${percent}%`;
|
2008 |
|
2009 |
|
2010 |
|
2011 | if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {
|
2012 | toggle(event.type === 'mouseenter');
|
2013 | }
|
2014 | },
|
2015 |
|
2016 | timeUpdate(event) {
|
2017 |
|
2018 | const invert = !is.element(this.elements.display.duration) && this.config.invertTime;
|
2019 |
|
2020 |
|
2021 | controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert);
|
2022 |
|
2023 |
|
2024 | if (event && event.type === 'timeupdate' && this.media.seeking) {
|
2025 | return;
|
2026 | }
|
2027 |
|
2028 |
|
2029 | controls.updateProgress.call(this, event);
|
2030 | },
|
2031 |
|
2032 | durationUpdate() {
|
2033 |
|
2034 | if (!this.supported.ui || !this.config.invertTime && this.currentTime) {
|
2035 | return;
|
2036 | }
|
2037 |
|
2038 |
|
2039 |
|
2040 |
|
2041 |
|
2042 | if (this.duration >= 2 ** 32) {
|
2043 | toggleHidden(this.elements.display.currentTime, true);
|
2044 | toggleHidden(this.elements.progress, true);
|
2045 | return;
|
2046 | }
|
2047 |
|
2048 |
|
2049 | if (is.element(this.elements.inputs.seek)) {
|
2050 | this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);
|
2051 | }
|
2052 |
|
2053 |
|
2054 | const hasDuration = is.element(this.elements.display.duration);
|
2055 |
|
2056 |
|
2057 | if (!hasDuration && this.config.displayDuration && this.paused) {
|
2058 | controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);
|
2059 | }
|
2060 |
|
2061 |
|
2062 | if (hasDuration) {
|
2063 | controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);
|
2064 | }
|
2065 | if (this.config.markers.enabled) {
|
2066 | controls.setMarkers.call(this);
|
2067 | }
|
2068 |
|
2069 |
|
2070 | controls.updateSeekTooltip.call(this);
|
2071 | },
|
2072 |
|
2073 | toggleMenuButton(setting, toggle) {
|
2074 | toggleHidden(this.elements.settings.buttons[setting], !toggle);
|
2075 | },
|
2076 |
|
2077 | updateSetting(setting, container, input) {
|
2078 | const pane = this.elements.settings.panels[setting];
|
2079 | let value = null;
|
2080 | let list = container;
|
2081 | if (setting === 'captions') {
|
2082 | value = this.currentTrack;
|
2083 | } else {
|
2084 | value = !is.empty(input) ? input : this[setting];
|
2085 |
|
2086 |
|
2087 | if (is.empty(value)) {
|
2088 | value = this.config[setting].default;
|
2089 | }
|
2090 |
|
2091 |
|
2092 | if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {
|
2093 | this.debug.warn(`Unsupported value of '${value}' for ${setting}`);
|
2094 | return;
|
2095 | }
|
2096 |
|
2097 |
|
2098 | if (!this.config[setting].options.includes(value)) {
|
2099 | this.debug.warn(`Disabled value of '${value}' for ${setting}`);
|
2100 | return;
|
2101 | }
|
2102 | }
|
2103 |
|
2104 |
|
2105 | if (!is.element(list)) {
|
2106 | list = pane && pane.querySelector('[role="menu"]');
|
2107 | }
|
2108 |
|
2109 |
|
2110 | if (!is.element(list)) {
|
2111 | return;
|
2112 | }
|
2113 |
|
2114 |
|
2115 | const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);
|
2116 | label.innerHTML = controls.getLabel.call(this, setting, value);
|
2117 |
|
2118 |
|
2119 | const target = list && list.querySelector(`[value="${value}"]`);
|
2120 | if (is.element(target)) {
|
2121 | target.checked = true;
|
2122 | }
|
2123 | },
|
2124 |
|
2125 | getLabel(setting, value) {
|
2126 | switch (setting) {
|
2127 | case 'speed':
|
2128 | return value === 1 ? i18n.get('normal', this.config) : `${value}×`;
|
2129 | case 'quality':
|
2130 | if (is.number(value)) {
|
2131 | const label = i18n.get(`qualityLabel.${value}`, this.config);
|
2132 | if (!label.length) {
|
2133 | return `${value}p`;
|
2134 | }
|
2135 | return label;
|
2136 | }
|
2137 | return toTitleCase(value);
|
2138 | case 'captions':
|
2139 | return captions.getLabel.call(this);
|
2140 | default:
|
2141 | return null;
|
2142 | }
|
2143 | },
|
2144 |
|
2145 | setQualityMenu(options) {
|
2146 |
|
2147 | if (!is.element(this.elements.settings.panels.quality)) {
|
2148 | return;
|
2149 | }
|
2150 | const type = 'quality';
|
2151 | const list = this.elements.settings.panels.quality.querySelector('[role="menu"]');
|
2152 |
|
2153 |
|
2154 | if (is.array(options)) {
|
2155 | this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality));
|
2156 | }
|
2157 |
|
2158 |
|
2159 | const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;
|
2160 | controls.toggleMenuButton.call(this, type, toggle);
|
2161 |
|
2162 |
|
2163 | emptyElement(list);
|
2164 |
|
2165 |
|
2166 | controls.checkMenu.call(this);
|
2167 |
|
2168 |
|
2169 | if (!toggle) {
|
2170 | return;
|
2171 | }
|
2172 |
|
2173 |
|
2174 | const getBadge = quality => {
|
2175 | const label = i18n.get(`qualityBadge.${quality}`, this.config);
|
2176 | if (!label.length) {
|
2177 | return null;
|
2178 | }
|
2179 | return controls.createBadge.call(this, label);
|
2180 | };
|
2181 |
|
2182 |
|
2183 | this.options.quality.sort((a, b) => {
|
2184 | const sorting = this.config.quality.options;
|
2185 | return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;
|
2186 | }).forEach(quality => {
|
2187 | controls.createMenuItem.call(this, {
|
2188 | value: quality,
|
2189 | list,
|
2190 | type,
|
2191 | title: controls.getLabel.call(this, 'quality', quality),
|
2192 | badge: getBadge(quality)
|
2193 | });
|
2194 | });
|
2195 | controls.updateSetting.call(this, type, list);
|
2196 | },
|
2197 |
|
2198 | |
2199 |
|
2200 |
|
2201 |
|
2202 |
|
2203 |
|
2204 |
|
2205 |
|
2206 |
|
2207 |
|
2208 |
|
2209 |
|
2210 |
|
2211 |
|
2212 |
|
2213 |
|
2214 |
|
2215 |
|
2216 |
|
2217 |
|
2218 |
|
2219 |
|
2220 |
|
2221 |
|
2222 |
|
2223 |
|
2224 |
|
2225 |
|
2226 |
|
2227 |
|
2228 |
|
2229 |
|
2230 |
|
2231 |
|
2232 |
|
2233 |
|
2234 |
|
2235 |
|
2236 |
|
2237 | setCaptionsMenu() {
|
2238 |
|
2239 | if (!is.element(this.elements.settings.panels.captions)) {
|
2240 | return;
|
2241 | }
|
2242 |
|
2243 |
|
2244 | const type = 'captions';
|
2245 | const list = this.elements.settings.panels.captions.querySelector('[role="menu"]');
|
2246 | const tracks = captions.getTracks.call(this);
|
2247 | const toggle = Boolean(tracks.length);
|
2248 |
|
2249 |
|
2250 | controls.toggleMenuButton.call(this, type, toggle);
|
2251 |
|
2252 |
|
2253 | emptyElement(list);
|
2254 |
|
2255 |
|
2256 | controls.checkMenu.call(this);
|
2257 |
|
2258 |
|
2259 | if (!toggle) {
|
2260 | return;
|
2261 | }
|
2262 |
|
2263 |
|
2264 | const options = tracks.map((track, value) => ({
|
2265 | value,
|
2266 | checked: this.captions.toggled && this.currentTrack === value,
|
2267 | title: captions.getLabel.call(this, track),
|
2268 | badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),
|
2269 | list,
|
2270 | type: 'language'
|
2271 | }));
|
2272 |
|
2273 |
|
2274 | options.unshift({
|
2275 | value: -1,
|
2276 | checked: !this.captions.toggled,
|
2277 | title: i18n.get('disabled', this.config),
|
2278 | list,
|
2279 | type: 'language'
|
2280 | });
|
2281 |
|
2282 |
|
2283 | options.forEach(controls.createMenuItem.bind(this));
|
2284 | controls.updateSetting.call(this, type, list);
|
2285 | },
|
2286 |
|
2287 | setSpeedMenu() {
|
2288 |
|
2289 | if (!is.element(this.elements.settings.panels.speed)) {
|
2290 | return;
|
2291 | }
|
2292 | const type = 'speed';
|
2293 | const list = this.elements.settings.panels.speed.querySelector('[role="menu"]');
|
2294 |
|
2295 |
|
2296 | this.options.speed = this.options.speed.filter(o => o >= this.minimumSpeed && o <= this.maximumSpeed);
|
2297 |
|
2298 |
|
2299 | const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;
|
2300 | controls.toggleMenuButton.call(this, type, toggle);
|
2301 |
|
2302 |
|
2303 | emptyElement(list);
|
2304 |
|
2305 |
|
2306 | controls.checkMenu.call(this);
|
2307 |
|
2308 |
|
2309 | if (!toggle) {
|
2310 | return;
|
2311 | }
|
2312 |
|
2313 |
|
2314 | this.options.speed.forEach(speed => {
|
2315 | controls.createMenuItem.call(this, {
|
2316 | value: speed,
|
2317 | list,
|
2318 | type,
|
2319 | title: controls.getLabel.call(this, 'speed', speed)
|
2320 | });
|
2321 | });
|
2322 | controls.updateSetting.call(this, type, list);
|
2323 | },
|
2324 |
|
2325 | checkMenu() {
|
2326 | const {
|
2327 | buttons
|
2328 | } = this.elements.settings;
|
2329 | const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden);
|
2330 | toggleHidden(this.elements.settings.menu, !visible);
|
2331 | },
|
2332 |
|
2333 | focusFirstMenuItem(pane, focusVisible = false) {
|
2334 | if (this.elements.settings.popup.hidden) {
|
2335 | return;
|
2336 | }
|
2337 | let target = pane;
|
2338 | if (!is.element(target)) {
|
2339 | target = Object.values(this.elements.settings.panels).find(p => !p.hidden);
|
2340 | }
|
2341 | const firstItem = target.querySelector('[role^="menuitem"]');
|
2342 | setFocus.call(this, firstItem, focusVisible);
|
2343 | },
|
2344 |
|
2345 | toggleMenu(input) {
|
2346 | const {
|
2347 | popup
|
2348 | } = this.elements.settings;
|
2349 | const button = this.elements.buttons.settings;
|
2350 |
|
2351 |
|
2352 | if (!is.element(popup) || !is.element(button)) {
|
2353 | return;
|
2354 | }
|
2355 |
|
2356 |
|
2357 | const {
|
2358 | hidden
|
2359 | } = popup;
|
2360 | let show = hidden;
|
2361 | if (is.boolean(input)) {
|
2362 | show = input;
|
2363 | } else if (is.keyboardEvent(input) && input.key === 'Escape') {
|
2364 | show = false;
|
2365 | } else if (is.event(input)) {
|
2366 |
|
2367 |
|
2368 | const target = is.function(input.composedPath) ? input.composedPath()[0] : input.target;
|
2369 | const isMenuItem = popup.contains(target);
|
2370 |
|
2371 |
|
2372 |
|
2373 |
|
2374 | if (isMenuItem || !isMenuItem && input.target !== button && show) {
|
2375 | return;
|
2376 | }
|
2377 | }
|
2378 |
|
2379 |
|
2380 | button.setAttribute('aria-expanded', show);
|
2381 |
|
2382 |
|
2383 | toggleHidden(popup, !show);
|
2384 |
|
2385 |
|
2386 | toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
2387 |
|
2388 |
|
2389 | if (show && is.keyboardEvent(input)) {
|
2390 | controls.focusFirstMenuItem.call(this, null, true);
|
2391 | } else if (!show && !hidden) {
|
2392 |
|
2393 | setFocus.call(this, button, is.keyboardEvent(input));
|
2394 | }
|
2395 | },
|
2396 |
|
2397 | getMenuSize(tab) {
|
2398 | const clone = tab.cloneNode(true);
|
2399 | clone.style.position = 'absolute';
|
2400 | clone.style.opacity = 0;
|
2401 | clone.removeAttribute('hidden');
|
2402 |
|
2403 |
|
2404 | tab.parentNode.appendChild(clone);
|
2405 |
|
2406 |
|
2407 | const width = clone.scrollWidth;
|
2408 | const height = clone.scrollHeight;
|
2409 |
|
2410 |
|
2411 | removeElement(clone);
|
2412 | return {
|
2413 | width,
|
2414 | height
|
2415 | };
|
2416 | },
|
2417 |
|
2418 | showMenuPanel(type = '', focusVisible = false) {
|
2419 | const target = this.elements.container.querySelector(`#plyr-settings-${this.id}-${type}`);
|
2420 |
|
2421 |
|
2422 | if (!is.element(target)) {
|
2423 | return;
|
2424 | }
|
2425 |
|
2426 |
|
2427 | const container = target.parentNode;
|
2428 | const current = Array.from(container.children).find(node => !node.hidden);
|
2429 |
|
2430 |
|
2431 | if (support.transitions && !support.reducedMotion) {
|
2432 |
|
2433 | container.style.width = `${current.scrollWidth}px`;
|
2434 | container.style.height = `${current.scrollHeight}px`;
|
2435 |
|
2436 |
|
2437 | const size = controls.getMenuSize.call(this, target);
|
2438 |
|
2439 |
|
2440 | const restore = event => {
|
2441 |
|
2442 | if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {
|
2443 | return;
|
2444 | }
|
2445 |
|
2446 |
|
2447 | container.style.width = '';
|
2448 | container.style.height = '';
|
2449 |
|
2450 |
|
2451 | off.call(this, container, transitionEndEvent, restore);
|
2452 | };
|
2453 |
|
2454 |
|
2455 | on.call(this, container, transitionEndEvent, restore);
|
2456 |
|
2457 |
|
2458 | container.style.width = `${size.width}px`;
|
2459 | container.style.height = `${size.height}px`;
|
2460 | }
|
2461 |
|
2462 |
|
2463 | toggleHidden(current, true);
|
2464 |
|
2465 |
|
2466 | toggleHidden(target, false);
|
2467 |
|
2468 |
|
2469 | controls.focusFirstMenuItem.call(this, target, focusVisible);
|
2470 | },
|
2471 |
|
2472 | setDownloadUrl() {
|
2473 | const button = this.elements.buttons.download;
|
2474 |
|
2475 |
|
2476 | if (!is.element(button)) {
|
2477 | return;
|
2478 | }
|
2479 |
|
2480 |
|
2481 | button.setAttribute('href', this.download);
|
2482 | },
|
2483 |
|
2484 | create(data) {
|
2485 | const {
|
2486 | bindMenuItemShortcuts,
|
2487 | createButton,
|
2488 | createProgress,
|
2489 | createRange,
|
2490 | createTime,
|
2491 | setQualityMenu,
|
2492 | setSpeedMenu,
|
2493 | showMenuPanel
|
2494 | } = controls;
|
2495 | this.elements.controls = null;
|
2496 |
|
2497 |
|
2498 | if (is.array(this.config.controls) && this.config.controls.includes('play-large')) {
|
2499 | this.elements.container.appendChild(createButton.call(this, 'play-large'));
|
2500 | }
|
2501 |
|
2502 |
|
2503 | const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));
|
2504 | this.elements.controls = container;
|
2505 |
|
2506 |
|
2507 | const defaultAttributes = {
|
2508 | class: 'plyr__controls__item'
|
2509 | };
|
2510 |
|
2511 |
|
2512 | dedupe(is.array(this.config.controls) ? this.config.controls : []).forEach(control => {
|
2513 |
|
2514 | if (control === 'restart') {
|
2515 | container.appendChild(createButton.call(this, 'restart', defaultAttributes));
|
2516 | }
|
2517 |
|
2518 |
|
2519 | if (control === 'rewind') {
|
2520 | container.appendChild(createButton.call(this, 'rewind', defaultAttributes));
|
2521 | }
|
2522 |
|
2523 |
|
2524 | if (control === 'play') {
|
2525 | container.appendChild(createButton.call(this, 'play', defaultAttributes));
|
2526 | }
|
2527 |
|
2528 |
|
2529 | if (control === 'fast-forward') {
|
2530 | container.appendChild(createButton.call(this, 'fast-forward', defaultAttributes));
|
2531 | }
|
2532 |
|
2533 |
|
2534 | if (control === 'progress') {
|
2535 | const progressContainer = createElement('div', {
|
2536 | class: `${defaultAttributes.class} plyr__progress__container`
|
2537 | });
|
2538 | const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));
|
2539 |
|
2540 |
|
2541 | progress.appendChild(createRange.call(this, 'seek', {
|
2542 | id: `plyr-seek-${data.id}`
|
2543 | }));
|
2544 |
|
2545 |
|
2546 | progress.appendChild(createProgress.call(this, 'buffer'));
|
2547 |
|
2548 |
|
2549 |
|
2550 |
|
2551 | if (this.config.tooltips.seek) {
|
2552 | const tooltip = createElement('span', {
|
2553 | class: this.config.classNames.tooltip
|
2554 | }, '00:00');
|
2555 | progress.appendChild(tooltip);
|
2556 | this.elements.display.seekTooltip = tooltip;
|
2557 | }
|
2558 | this.elements.progress = progress;
|
2559 | progressContainer.appendChild(this.elements.progress);
|
2560 | container.appendChild(progressContainer);
|
2561 | }
|
2562 |
|
2563 |
|
2564 | if (control === 'current-time') {
|
2565 | container.appendChild(createTime.call(this, 'currentTime', defaultAttributes));
|
2566 | }
|
2567 |
|
2568 |
|
2569 | if (control === 'duration') {
|
2570 | container.appendChild(createTime.call(this, 'duration', defaultAttributes));
|
2571 | }
|
2572 |
|
2573 |
|
2574 | if (control === 'mute' || control === 'volume') {
|
2575 | let {
|
2576 | volume
|
2577 | } = this.elements;
|
2578 |
|
2579 |
|
2580 | if (!is.element(volume) || !container.contains(volume)) {
|
2581 | volume = createElement('div', extend({}, defaultAttributes, {
|
2582 | class: `${defaultAttributes.class} plyr__volume`.trim()
|
2583 | }));
|
2584 | this.elements.volume = volume;
|
2585 | container.appendChild(volume);
|
2586 | }
|
2587 |
|
2588 |
|
2589 | if (control === 'mute') {
|
2590 | volume.appendChild(createButton.call(this, 'mute'));
|
2591 | }
|
2592 |
|
2593 |
|
2594 |
|
2595 |
|
2596 | if (control === 'volume' && !browser.isIos && !browser.isIPadOS) {
|
2597 |
|
2598 | const attributes = {
|
2599 | max: 1,
|
2600 | step: 0.05,
|
2601 | value: this.config.volume
|
2602 | };
|
2603 |
|
2604 |
|
2605 | volume.appendChild(createRange.call(this, 'volume', extend(attributes, {
|
2606 | id: `plyr-volume-${data.id}`
|
2607 | })));
|
2608 | }
|
2609 | }
|
2610 |
|
2611 |
|
2612 | if (control === 'captions') {
|
2613 | container.appendChild(createButton.call(this, 'captions', defaultAttributes));
|
2614 | }
|
2615 |
|
2616 |
|
2617 | if (control === 'settings' && !is.empty(this.config.settings)) {
|
2618 | const wrapper = createElement('div', extend({}, defaultAttributes, {
|
2619 | class: `${defaultAttributes.class} plyr__menu`.trim(),
|
2620 | hidden: ''
|
2621 | }));
|
2622 | wrapper.appendChild(createButton.call(this, 'settings', {
|
2623 | 'aria-haspopup': true,
|
2624 | 'aria-controls': `plyr-settings-${data.id}`,
|
2625 | 'aria-expanded': false
|
2626 | }));
|
2627 | const popup = createElement('div', {
|
2628 | class: 'plyr__menu__container',
|
2629 | id: `plyr-settings-${data.id}`,
|
2630 | hidden: ''
|
2631 | });
|
2632 | const inner = createElement('div');
|
2633 | const home = createElement('div', {
|
2634 | id: `plyr-settings-${data.id}-home`
|
2635 | });
|
2636 |
|
2637 |
|
2638 | const menu = createElement('div', {
|
2639 | role: 'menu'
|
2640 | });
|
2641 | home.appendChild(menu);
|
2642 | inner.appendChild(home);
|
2643 | this.elements.settings.panels.home = home;
|
2644 |
|
2645 |
|
2646 | this.config.settings.forEach(type => {
|
2647 |
|
2648 | const menuItem = createElement('button', extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {
|
2649 | type: 'button',
|
2650 | class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,
|
2651 | role: 'menuitem',
|
2652 | 'aria-haspopup': true,
|
2653 | hidden: ''
|
2654 | }));
|
2655 |
|
2656 |
|
2657 | bindMenuItemShortcuts.call(this, menuItem, type);
|
2658 |
|
2659 |
|
2660 | on.call(this, menuItem, 'click', () => {
|
2661 | showMenuPanel.call(this, type, false);
|
2662 | });
|
2663 | const flex = createElement('span', null, i18n.get(type, this.config));
|
2664 | const value = createElement('span', {
|
2665 | class: this.config.classNames.menu.value
|
2666 | });
|
2667 |
|
2668 |
|
2669 | value.innerHTML = data[type];
|
2670 | flex.appendChild(value);
|
2671 | menuItem.appendChild(flex);
|
2672 | menu.appendChild(menuItem);
|
2673 |
|
2674 |
|
2675 | const pane = createElement('div', {
|
2676 | id: `plyr-settings-${data.id}-${type}`,
|
2677 | hidden: ''
|
2678 | });
|
2679 |
|
2680 |
|
2681 | const backButton = createElement('button', {
|
2682 | type: 'button',
|
2683 | class: `${this.config.classNames.control} ${this.config.classNames.control}--back`
|
2684 | });
|
2685 |
|
2686 |
|
2687 | backButton.appendChild(createElement('span', {
|
2688 | 'aria-hidden': true
|
2689 | }, i18n.get(type, this.config)));
|
2690 |
|
2691 |
|
2692 | backButton.appendChild(createElement('span', {
|
2693 | class: this.config.classNames.hidden
|
2694 | }, i18n.get('menuBack', this.config)));
|
2695 |
|
2696 |
|
2697 | on.call(this, pane, 'keydown', event => {
|
2698 | if (event.key !== 'ArrowLeft') return;
|
2699 |
|
2700 |
|
2701 | event.preventDefault();
|
2702 | event.stopPropagation();
|
2703 |
|
2704 |
|
2705 | showMenuPanel.call(this, 'home', true);
|
2706 | }, false);
|
2707 |
|
2708 |
|
2709 | on.call(this, backButton, 'click', () => {
|
2710 | showMenuPanel.call(this, 'home', false);
|
2711 | });
|
2712 |
|
2713 |
|
2714 | pane.appendChild(backButton);
|
2715 |
|
2716 |
|
2717 | pane.appendChild(createElement('div', {
|
2718 | role: 'menu'
|
2719 | }));
|
2720 | inner.appendChild(pane);
|
2721 | this.elements.settings.buttons[type] = menuItem;
|
2722 | this.elements.settings.panels[type] = pane;
|
2723 | });
|
2724 | popup.appendChild(inner);
|
2725 | wrapper.appendChild(popup);
|
2726 | container.appendChild(wrapper);
|
2727 | this.elements.settings.popup = popup;
|
2728 | this.elements.settings.menu = wrapper;
|
2729 | }
|
2730 |
|
2731 |
|
2732 | if (control === 'pip' && support.pip) {
|
2733 | container.appendChild(createButton.call(this, 'pip', defaultAttributes));
|
2734 | }
|
2735 |
|
2736 |
|
2737 | if (control === 'airplay' && support.airplay) {
|
2738 | container.appendChild(createButton.call(this, 'airplay', defaultAttributes));
|
2739 | }
|
2740 |
|
2741 |
|
2742 | if (control === 'download') {
|
2743 | const attributes = extend({}, defaultAttributes, {
|
2744 | element: 'a',
|
2745 | href: this.download,
|
2746 | target: '_blank'
|
2747 | });
|
2748 |
|
2749 |
|
2750 | if (this.isHTML5) {
|
2751 | attributes.download = '';
|
2752 | }
|
2753 | const {
|
2754 | download
|
2755 | } = this.config.urls;
|
2756 | if (!is.url(download) && this.isEmbed) {
|
2757 | extend(attributes, {
|
2758 | icon: `logo-${this.provider}`,
|
2759 | label: this.provider
|
2760 | });
|
2761 | }
|
2762 | container.appendChild(createButton.call(this, 'download', attributes));
|
2763 | }
|
2764 |
|
2765 |
|
2766 | if (control === 'fullscreen') {
|
2767 | container.appendChild(createButton.call(this, 'fullscreen', defaultAttributes));
|
2768 | }
|
2769 | });
|
2770 |
|
2771 |
|
2772 | if (this.isHTML5) {
|
2773 | setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
2774 | }
|
2775 | setSpeedMenu.call(this);
|
2776 | return container;
|
2777 | },
|
2778 |
|
2779 | inject() {
|
2780 |
|
2781 | if (this.config.loadSprite) {
|
2782 | const icon = controls.getIconUrl.call(this);
|
2783 |
|
2784 |
|
2785 | if (icon.cors) {
|
2786 | loadSprite(icon.url, 'sprite-plyr');
|
2787 | }
|
2788 | }
|
2789 |
|
2790 |
|
2791 | this.id = Math.floor(Math.random() * 10000);
|
2792 |
|
2793 |
|
2794 | let container = null;
|
2795 | this.elements.controls = null;
|
2796 |
|
2797 |
|
2798 | const props = {
|
2799 | id: this.id,
|
2800 | seektime: this.config.seekTime,
|
2801 | title: this.config.title
|
2802 | };
|
2803 | let update = true;
|
2804 |
|
2805 |
|
2806 | if (is.function(this.config.controls)) {
|
2807 | this.config.controls = this.config.controls.call(this, props);
|
2808 | }
|
2809 |
|
2810 |
|
2811 | if (!this.config.controls) {
|
2812 | this.config.controls = [];
|
2813 | }
|
2814 | if (is.element(this.config.controls) || is.string(this.config.controls)) {
|
2815 |
|
2816 | container = this.config.controls;
|
2817 | } else {
|
2818 |
|
2819 | container = controls.create.call(this, {
|
2820 | id: this.id,
|
2821 | seektime: this.config.seekTime,
|
2822 | speed: this.speed,
|
2823 | quality: this.quality,
|
2824 | captions: captions.getLabel.call(this)
|
2825 |
|
2826 |
|
2827 | });
|
2828 |
|
2829 | update = false;
|
2830 | }
|
2831 |
|
2832 |
|
2833 | const replace = input => {
|
2834 | let result = input;
|
2835 | Object.entries(props).forEach(([key, value]) => {
|
2836 | result = replaceAll(result, `{${key}}`, value);
|
2837 | });
|
2838 | return result;
|
2839 | };
|
2840 |
|
2841 |
|
2842 | if (update) {
|
2843 | if (is.string(this.config.controls)) {
|
2844 | container = replace(container);
|
2845 | }
|
2846 | }
|
2847 |
|
2848 |
|
2849 | let target;
|
2850 |
|
2851 |
|
2852 | if (is.string(this.config.selectors.controls.container)) {
|
2853 | target = document.querySelector(this.config.selectors.controls.container);
|
2854 | }
|
2855 |
|
2856 |
|
2857 | if (!is.element(target)) {
|
2858 | target = this.elements.container;
|
2859 | }
|
2860 |
|
2861 |
|
2862 | const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';
|
2863 | target[insertMethod]('afterbegin', container);
|
2864 |
|
2865 |
|
2866 | if (!is.element(this.elements.controls)) {
|
2867 | controls.findElements.call(this);
|
2868 | }
|
2869 |
|
2870 |
|
2871 | if (!is.empty(this.elements.buttons)) {
|
2872 | const addProperty = button => {
|
2873 | const className = this.config.classNames.controlPressed;
|
2874 | button.setAttribute('aria-pressed', 'false');
|
2875 | Object.defineProperty(button, 'pressed', {
|
2876 | configurable: true,
|
2877 | enumerable: true,
|
2878 | get() {
|
2879 | return hasClass(button, className);
|
2880 | },
|
2881 | set(pressed = false) {
|
2882 | toggleClass(button, className, pressed);
|
2883 | button.setAttribute('aria-pressed', pressed ? 'true' : 'false');
|
2884 | }
|
2885 | });
|
2886 | };
|
2887 |
|
2888 |
|
2889 | Object.values(this.elements.buttons).filter(Boolean).forEach(button => {
|
2890 | if (is.array(button) || is.nodeList(button)) {
|
2891 | Array.from(button).filter(Boolean).forEach(addProperty);
|
2892 | } else {
|
2893 | addProperty(button);
|
2894 | }
|
2895 | });
|
2896 | }
|
2897 |
|
2898 |
|
2899 | if (browser.isEdge) {
|
2900 | repaint(target);
|
2901 | }
|
2902 |
|
2903 |
|
2904 | if (this.config.tooltips.controls) {
|
2905 | const {
|
2906 | classNames,
|
2907 | selectors
|
2908 | } = this.config;
|
2909 | const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;
|
2910 | const labels = getElements.call(this, selector);
|
2911 | Array.from(labels).forEach(label => {
|
2912 | toggleClass(label, this.config.classNames.hidden, false);
|
2913 | toggleClass(label, this.config.classNames.tooltip, true);
|
2914 | });
|
2915 | }
|
2916 | },
|
2917 |
|
2918 | setMediaMetadata() {
|
2919 | try {
|
2920 | if ('mediaSession' in navigator) {
|
2921 | navigator.mediaSession.metadata = new window.MediaMetadata({
|
2922 | title: this.config.mediaMetadata.title,
|
2923 | artist: this.config.mediaMetadata.artist,
|
2924 | album: this.config.mediaMetadata.album,
|
2925 | artwork: this.config.mediaMetadata.artwork
|
2926 | });
|
2927 | }
|
2928 | } catch (_) {
|
2929 |
|
2930 | }
|
2931 | },
|
2932 |
|
2933 | setMarkers() {
|
2934 | var _this$config$markers2, _this$config$markers3;
|
2935 | if (!this.duration || this.elements.markers) return;
|
2936 |
|
2937 |
|
2938 | const points = (_this$config$markers2 = this.config.markers) === null || _this$config$markers2 === void 0 ? void 0 : (_this$config$markers3 = _this$config$markers2.points) === null || _this$config$markers3 === void 0 ? void 0 : _this$config$markers3.filter(({
|
2939 | time
|
2940 | }) => time > 0 && time < this.duration);
|
2941 | if (!(points !== null && points !== void 0 && points.length)) return;
|
2942 | const containerFragment = document.createDocumentFragment();
|
2943 | const pointsFragment = document.createDocumentFragment();
|
2944 | let tipElement = null;
|
2945 | const tipVisible = `${this.config.classNames.tooltip}--visible`;
|
2946 | const toggleTip = show => toggleClass(tipElement, tipVisible, show);
|
2947 |
|
2948 |
|
2949 | points.forEach(point => {
|
2950 | const markerElement = createElement('span', {
|
2951 | class: this.config.classNames.marker
|
2952 | }, '');
|
2953 | const left = `${point.time / this.duration * 100}%`;
|
2954 | if (tipElement) {
|
2955 |
|
2956 | markerElement.addEventListener('mouseenter', () => {
|
2957 | if (point.label) return;
|
2958 | tipElement.style.left = left;
|
2959 | tipElement.innerHTML = point.label;
|
2960 | toggleTip(true);
|
2961 | });
|
2962 |
|
2963 |
|
2964 | markerElement.addEventListener('mouseleave', () => {
|
2965 | toggleTip(false);
|
2966 | });
|
2967 | }
|
2968 | markerElement.addEventListener('click', () => {
|
2969 | this.currentTime = point.time;
|
2970 | });
|
2971 | markerElement.style.left = left;
|
2972 | pointsFragment.appendChild(markerElement);
|
2973 | });
|
2974 | containerFragment.appendChild(pointsFragment);
|
2975 |
|
2976 |
|
2977 | if (!this.config.tooltips.seek) {
|
2978 | tipElement = createElement('span', {
|
2979 | class: this.config.classNames.tooltip
|
2980 | }, '');
|
2981 | containerFragment.appendChild(tipElement);
|
2982 | }
|
2983 | this.elements.markers = {
|
2984 | points: pointsFragment,
|
2985 | tip: tipElement
|
2986 | };
|
2987 | this.elements.progress.appendChild(containerFragment);
|
2988 | }
|
2989 | };
|
2990 |
|
2991 |
|
2992 |
|
2993 |
|
2994 |
|
2995 |
|
2996 |
|
2997 |
|
2998 | function parseUrl(input, safe = true) {
|
2999 | let url = input;
|
3000 | if (safe) {
|
3001 | const parser = document.createElement('a');
|
3002 | parser.href = url;
|
3003 | url = parser.href;
|
3004 | }
|
3005 | try {
|
3006 | return new URL(url);
|
3007 | } catch (_) {
|
3008 | return null;
|
3009 | }
|
3010 | }
|
3011 |
|
3012 |
|
3013 | function buildUrlParams(input) {
|
3014 | const params = new URLSearchParams();
|
3015 | if (is.object(input)) {
|
3016 | Object.entries(input).forEach(([key, value]) => {
|
3017 | params.set(key, value);
|
3018 | });
|
3019 | }
|
3020 | return params;
|
3021 | }
|
3022 |
|
3023 |
|
3024 | const captions = {
|
3025 |
|
3026 | setup() {
|
3027 |
|
3028 | if (!this.supported.ui) {
|
3029 | return;
|
3030 | }
|
3031 |
|
3032 |
|
3033 | if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) {
|
3034 |
|
3035 | if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {
|
3036 | controls.setCaptionsMenu.call(this);
|
3037 | }
|
3038 | return;
|
3039 | }
|
3040 |
|
3041 |
|
3042 | if (!is.element(this.elements.captions)) {
|
3043 | this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));
|
3044 | this.elements.captions.setAttribute('dir', 'auto');
|
3045 | insertAfter(this.elements.captions, this.elements.wrapper);
|
3046 | }
|
3047 |
|
3048 |
|
3049 |
|
3050 | if (browser.isIE && window.URL) {
|
3051 | const elements = this.media.querySelectorAll('track');
|
3052 | Array.from(elements).forEach(track => {
|
3053 | const src = track.getAttribute('src');
|
3054 | const url = parseUrl(src);
|
3055 | if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) {
|
3056 | fetch(src, 'blob').then(blob => {
|
3057 | track.setAttribute('src', window.URL.createObjectURL(blob));
|
3058 | }).catch(() => {
|
3059 | removeElement(track);
|
3060 | });
|
3061 | }
|
3062 | });
|
3063 | }
|
3064 |
|
3065 |
|
3066 |
|
3067 |
|
3068 |
|
3069 |
|
3070 |
|
3071 |
|
3072 | const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];
|
3073 | const languages = dedupe(browserLanguages.map(language => language.split('-')[0]));
|
3074 | let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();
|
3075 |
|
3076 |
|
3077 | if (language === 'auto') {
|
3078 | [language] = languages;
|
3079 | }
|
3080 | let active = this.storage.get('captions');
|
3081 | if (!is.boolean(active)) {
|
3082 | ({
|
3083 | active
|
3084 | } = this.config.captions);
|
3085 | }
|
3086 | Object.assign(this.captions, {
|
3087 | toggled: false,
|
3088 | active,
|
3089 | language,
|
3090 | languages
|
3091 | });
|
3092 |
|
3093 |
|
3094 | if (this.isHTML5) {
|
3095 | const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';
|
3096 | on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));
|
3097 | }
|
3098 |
|
3099 |
|
3100 | setTimeout(captions.update.bind(this), 0);
|
3101 | },
|
3102 |
|
3103 | update() {
|
3104 | const tracks = captions.getTracks.call(this, true);
|
3105 |
|
3106 | const {
|
3107 | active,
|
3108 | language,
|
3109 | meta,
|
3110 | currentTrackNode
|
3111 | } = this.captions;
|
3112 | const languageExists = Boolean(tracks.find(track => track.language === language));
|
3113 |
|
3114 |
|
3115 | if (this.isHTML5 && this.isVideo) {
|
3116 | tracks.filter(track => !meta.get(track)).forEach(track => {
|
3117 | this.debug.log('Track added', track);
|
3118 |
|
3119 |
|
3120 | meta.set(track, {
|
3121 | default: track.mode === 'showing'
|
3122 | });
|
3123 |
|
3124 |
|
3125 |
|
3126 |
|
3127 |
|
3128 | if (track.mode === 'showing') {
|
3129 |
|
3130 | track.mode = 'hidden';
|
3131 | }
|
3132 |
|
3133 |
|
3134 | on.call(this, track, 'cuechange', () => captions.updateCues.call(this));
|
3135 | });
|
3136 | }
|
3137 |
|
3138 |
|
3139 | if (languageExists && this.language !== language || !tracks.includes(currentTrackNode)) {
|
3140 | captions.setLanguage.call(this, language);
|
3141 | captions.toggle.call(this, active && languageExists);
|
3142 | }
|
3143 |
|
3144 |
|
3145 | if (this.elements) {
|
3146 | toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));
|
3147 | }
|
3148 |
|
3149 |
|
3150 | if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {
|
3151 | controls.setCaptionsMenu.call(this);
|
3152 | }
|
3153 | },
|
3154 |
|
3155 |
|
3156 | toggle(input, passive = true) {
|
3157 |
|
3158 | if (!this.supported.ui) {
|
3159 | return;
|
3160 | }
|
3161 | const {
|
3162 | toggled
|
3163 | } = this.captions;
|
3164 | const activeClass = this.config.classNames.captions.active;
|
3165 |
|
3166 |
|
3167 | const active = is.nullOrUndefined(input) ? !toggled : input;
|
3168 |
|
3169 |
|
3170 | if (active !== toggled) {
|
3171 |
|
3172 | if (!passive) {
|
3173 | this.captions.active = active;
|
3174 | this.storage.set({
|
3175 | captions: active
|
3176 | });
|
3177 | }
|
3178 |
|
3179 |
|
3180 | if (!this.language && active && !passive) {
|
3181 | const tracks = captions.getTracks.call(this);
|
3182 | const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true);
|
3183 |
|
3184 |
|
3185 | this.captions.language = track.language;
|
3186 |
|
3187 |
|
3188 | captions.set.call(this, tracks.indexOf(track));
|
3189 | return;
|
3190 | }
|
3191 |
|
3192 |
|
3193 | if (this.elements.buttons.captions) {
|
3194 | this.elements.buttons.captions.pressed = active;
|
3195 | }
|
3196 |
|
3197 |
|
3198 | toggleClass(this.elements.container, activeClass, active);
|
3199 | this.captions.toggled = active;
|
3200 |
|
3201 |
|
3202 | controls.updateSetting.call(this, 'captions');
|
3203 |
|
3204 |
|
3205 | triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');
|
3206 | }
|
3207 |
|
3208 |
|
3209 |
|
3210 | setTimeout(() => {
|
3211 | if (active && this.captions.toggled) {
|
3212 | this.captions.currentTrackNode.mode = 'hidden';
|
3213 | }
|
3214 | });
|
3215 | },
|
3216 |
|
3217 |
|
3218 | set(index, passive = true) {
|
3219 | const tracks = captions.getTracks.call(this);
|
3220 |
|
3221 |
|
3222 | if (index === -1) {
|
3223 | captions.toggle.call(this, false, passive);
|
3224 | return;
|
3225 | }
|
3226 | if (!is.number(index)) {
|
3227 | this.debug.warn('Invalid caption argument', index);
|
3228 | return;
|
3229 | }
|
3230 | if (!(index in tracks)) {
|
3231 | this.debug.warn('Track not found', index);
|
3232 | return;
|
3233 | }
|
3234 | if (this.captions.currentTrack !== index) {
|
3235 | this.captions.currentTrack = index;
|
3236 | const track = tracks[index];
|
3237 | const {
|
3238 | language
|
3239 | } = track || {};
|
3240 |
|
3241 |
|
3242 | this.captions.currentTrackNode = track;
|
3243 |
|
3244 |
|
3245 | controls.updateSetting.call(this, 'captions');
|
3246 |
|
3247 |
|
3248 | if (!passive) {
|
3249 | this.captions.language = language;
|
3250 | this.storage.set({
|
3251 | language
|
3252 | });
|
3253 | }
|
3254 |
|
3255 |
|
3256 | if (this.isVimeo) {
|
3257 | this.embed.enableTextTrack(language);
|
3258 | }
|
3259 |
|
3260 |
|
3261 | triggerEvent.call(this, this.media, 'languagechange');
|
3262 | }
|
3263 |
|
3264 |
|
3265 | captions.toggle.call(this, true, passive);
|
3266 | if (this.isHTML5 && this.isVideo) {
|
3267 |
|
3268 | captions.updateCues.call(this);
|
3269 | }
|
3270 | },
|
3271 |
|
3272 |
|
3273 | setLanguage(input, passive = true) {
|
3274 | if (!is.string(input)) {
|
3275 | this.debug.warn('Invalid language argument', input);
|
3276 | return;
|
3277 | }
|
3278 |
|
3279 | const language = input.toLowerCase();
|
3280 | this.captions.language = language;
|
3281 |
|
3282 |
|
3283 | const tracks = captions.getTracks.call(this);
|
3284 | const track = captions.findTrack.call(this, [language]);
|
3285 | captions.set.call(this, tracks.indexOf(track), passive);
|
3286 | },
|
3287 |
|
3288 |
|
3289 |
|
3290 | getTracks(update = false) {
|
3291 |
|
3292 | const tracks = Array.from((this.media || {}).textTracks || []);
|
3293 |
|
3294 |
|
3295 | return tracks.filter(track => !this.isHTML5 || update || this.captions.meta.has(track)).filter(track => ['captions', 'subtitles'].includes(track.kind));
|
3296 | },
|
3297 |
|
3298 | findTrack(languages, force = false) {
|
3299 | const tracks = captions.getTracks.call(this);
|
3300 | const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default);
|
3301 | const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));
|
3302 | let track;
|
3303 | languages.every(language => {
|
3304 | track = sorted.find(t => t.language === language);
|
3305 | return !track;
|
3306 | });
|
3307 |
|
3308 |
|
3309 | return track || (force ? sorted[0] : undefined);
|
3310 | },
|
3311 |
|
3312 | getCurrentTrack() {
|
3313 | return captions.getTracks.call(this)[this.currentTrack];
|
3314 | },
|
3315 |
|
3316 | getLabel(track) {
|
3317 | let currentTrack = track;
|
3318 | if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {
|
3319 | currentTrack = captions.getCurrentTrack.call(this);
|
3320 | }
|
3321 | if (is.track(currentTrack)) {
|
3322 | if (!is.empty(currentTrack.label)) {
|
3323 | return currentTrack.label;
|
3324 | }
|
3325 | if (!is.empty(currentTrack.language)) {
|
3326 | return track.language.toUpperCase();
|
3327 | }
|
3328 | return i18n.get('enabled', this.config);
|
3329 | }
|
3330 | return i18n.get('disabled', this.config);
|
3331 | },
|
3332 |
|
3333 |
|
3334 | updateCues(input) {
|
3335 |
|
3336 | if (!this.supported.ui) {
|
3337 | return;
|
3338 | }
|
3339 | if (!is.element(this.elements.captions)) {
|
3340 | this.debug.warn('No captions element to render to');
|
3341 | return;
|
3342 | }
|
3343 |
|
3344 |
|
3345 | if (!is.nullOrUndefined(input) && !Array.isArray(input)) {
|
3346 | this.debug.warn('updateCues: Invalid input', input);
|
3347 | return;
|
3348 | }
|
3349 | let cues = input;
|
3350 |
|
3351 |
|
3352 | if (!cues) {
|
3353 | const track = captions.getCurrentTrack.call(this);
|
3354 | cues = Array.from((track || {}).activeCues || []).map(cue => cue.getCueAsHTML()).map(getHTML);
|
3355 | }
|
3356 |
|
3357 |
|
3358 | const content = cues.map(cueText => cueText.trim()).join('\n');
|
3359 | const changed = content !== this.elements.captions.innerHTML;
|
3360 | if (changed) {
|
3361 |
|
3362 | emptyElement(this.elements.captions);
|
3363 | const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));
|
3364 | caption.innerHTML = content;
|
3365 | this.elements.captions.appendChild(caption);
|
3366 |
|
3367 |
|
3368 | triggerEvent.call(this, this.media, 'cuechange');
|
3369 | }
|
3370 | }
|
3371 | };
|
3372 |
|
3373 |
|
3374 |
|
3375 |
|
3376 |
|
3377 | const defaults = {
|
3378 |
|
3379 | enabled: true,
|
3380 |
|
3381 | title: '',
|
3382 |
|
3383 | debug: false,
|
3384 |
|
3385 | autoplay: false,
|
3386 |
|
3387 | autopause: true,
|
3388 |
|
3389 | playsinline: true,
|
3390 |
|
3391 | seekTime: 10,
|
3392 |
|
3393 | volume: 1,
|
3394 | muted: false,
|
3395 |
|
3396 | duration: null,
|
3397 |
|
3398 |
|
3399 | displayDuration: true,
|
3400 |
|
3401 | invertTime: true,
|
3402 |
|
3403 | toggleInvert: true,
|
3404 |
|
3405 |
|
3406 | ratio: null,
|
3407 |
|
3408 | clickToPlay: true,
|
3409 |
|
3410 | hideControls: true,
|
3411 |
|
3412 | resetOnEnd: false,
|
3413 |
|
3414 | disableContextMenu: true,
|
3415 |
|
3416 | loadSprite: true,
|
3417 | iconPrefix: 'plyr',
|
3418 | iconUrl: 'https://cdn.plyr.io/3.7.8/plyr.svg',
|
3419 |
|
3420 | blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
|
3421 |
|
3422 | quality: {
|
3423 | default: 576,
|
3424 |
|
3425 | options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],
|
3426 | forced: false,
|
3427 | onChange: null
|
3428 | },
|
3429 |
|
3430 | loop: {
|
3431 | active: false
|
3432 |
|
3433 |
|
3434 | },
|
3435 |
|
3436 |
|
3437 | speed: {
|
3438 | selected: 1,
|
3439 |
|
3440 | options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4]
|
3441 | },
|
3442 |
|
3443 | keyboard: {
|
3444 | focused: true,
|
3445 | global: false
|
3446 | },
|
3447 |
|
3448 | tooltips: {
|
3449 | controls: false,
|
3450 | seek: true
|
3451 | },
|
3452 |
|
3453 | captions: {
|
3454 | active: false,
|
3455 | language: 'auto',
|
3456 |
|
3457 |
|
3458 | update: false
|
3459 | },
|
3460 |
|
3461 | fullscreen: {
|
3462 | enabled: true,
|
3463 |
|
3464 | fallback: true,
|
3465 |
|
3466 | iosNative: false
|
3467 |
|
3468 |
|
3469 |
|
3470 | },
|
3471 |
|
3472 |
|
3473 | storage: {
|
3474 | enabled: true,
|
3475 | key: 'plyr'
|
3476 | },
|
3477 |
|
3478 | controls: ['play-large',
|
3479 |
|
3480 |
|
3481 | 'play',
|
3482 |
|
3483 | 'progress', 'current-time',
|
3484 |
|
3485 | 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay',
|
3486 |
|
3487 | 'fullscreen'],
|
3488 | settings: ['captions', 'quality', 'speed'],
|
3489 |
|
3490 | i18n: {
|
3491 | restart: 'Restart',
|
3492 | rewind: 'Rewind {seektime}s',
|
3493 | play: 'Play',
|
3494 | pause: 'Pause',
|
3495 | fastForward: 'Forward {seektime}s',
|
3496 | seek: 'Seek',
|
3497 | seekLabel: '{currentTime} of {duration}',
|
3498 | played: 'Played',
|
3499 | buffered: 'Buffered',
|
3500 | currentTime: 'Current time',
|
3501 | duration: 'Duration',
|
3502 | volume: 'Volume',
|
3503 | mute: 'Mute',
|
3504 | unmute: 'Unmute',
|
3505 | enableCaptions: 'Enable captions',
|
3506 | disableCaptions: 'Disable captions',
|
3507 | download: 'Download',
|
3508 | enterFullscreen: 'Enter fullscreen',
|
3509 | exitFullscreen: 'Exit fullscreen',
|
3510 | frameTitle: 'Player for {title}',
|
3511 | captions: 'Captions',
|
3512 | settings: 'Settings',
|
3513 | pip: 'PIP',
|
3514 | menuBack: 'Go back to previous menu',
|
3515 | speed: 'Speed',
|
3516 | normal: 'Normal',
|
3517 | quality: 'Quality',
|
3518 | loop: 'Loop',
|
3519 | start: 'Start',
|
3520 | end: 'End',
|
3521 | all: 'All',
|
3522 | reset: 'Reset',
|
3523 | disabled: 'Disabled',
|
3524 | enabled: 'Enabled',
|
3525 | advertisement: 'Ad',
|
3526 | qualityBadge: {
|
3527 | 2160: '4K',
|
3528 | 1440: 'HD',
|
3529 | 1080: 'HD',
|
3530 | 720: 'HD',
|
3531 | 576: 'SD',
|
3532 | 480: 'SD'
|
3533 | }
|
3534 | },
|
3535 |
|
3536 | urls: {
|
3537 | download: null,
|
3538 | vimeo: {
|
3539 | sdk: 'https://player.vimeo.com/api/player.js',
|
3540 | iframe: 'https://player.vimeo.com/video/{0}?{1}',
|
3541 | api: 'https://vimeo.com/api/oembed.json?url={0}'
|
3542 | },
|
3543 | youtube: {
|
3544 | sdk: 'https://www.youtube.com/iframe_api',
|
3545 | api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}'
|
3546 | },
|
3547 | googleIMA: {
|
3548 | sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js'
|
3549 | }
|
3550 | },
|
3551 |
|
3552 | listeners: {
|
3553 | seek: null,
|
3554 | play: null,
|
3555 | pause: null,
|
3556 | restart: null,
|
3557 | rewind: null,
|
3558 | fastForward: null,
|
3559 | mute: null,
|
3560 | volume: null,
|
3561 | captions: null,
|
3562 | download: null,
|
3563 | fullscreen: null,
|
3564 | pip: null,
|
3565 | airplay: null,
|
3566 | speed: null,
|
3567 | quality: null,
|
3568 | loop: null,
|
3569 | language: null
|
3570 | },
|
3571 |
|
3572 | events: [
|
3573 |
|
3574 |
|
3575 | 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange',
|
3576 |
|
3577 | 'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready',
|
3578 |
|
3579 | 'statechange',
|
3580 |
|
3581 | 'qualitychange',
|
3582 |
|
3583 | 'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'],
|
3584 |
|
3585 |
|
3586 | selectors: {
|
3587 | editable: 'input, textarea, select, [contenteditable]',
|
3588 | container: '.plyr',
|
3589 | controls: {
|
3590 | container: null,
|
3591 | wrapper: '.plyr__controls'
|
3592 | },
|
3593 | labels: '[data-plyr]',
|
3594 | buttons: {
|
3595 | play: '[data-plyr="play"]',
|
3596 | pause: '[data-plyr="pause"]',
|
3597 | restart: '[data-plyr="restart"]',
|
3598 | rewind: '[data-plyr="rewind"]',
|
3599 | fastForward: '[data-plyr="fast-forward"]',
|
3600 | mute: '[data-plyr="mute"]',
|
3601 | captions: '[data-plyr="captions"]',
|
3602 | download: '[data-plyr="download"]',
|
3603 | fullscreen: '[data-plyr="fullscreen"]',
|
3604 | pip: '[data-plyr="pip"]',
|
3605 | airplay: '[data-plyr="airplay"]',
|
3606 | settings: '[data-plyr="settings"]',
|
3607 | loop: '[data-plyr="loop"]'
|
3608 | },
|
3609 | inputs: {
|
3610 | seek: '[data-plyr="seek"]',
|
3611 | volume: '[data-plyr="volume"]',
|
3612 | speed: '[data-plyr="speed"]',
|
3613 | language: '[data-plyr="language"]',
|
3614 | quality: '[data-plyr="quality"]'
|
3615 | },
|
3616 | display: {
|
3617 | currentTime: '.plyr__time--current',
|
3618 | duration: '.plyr__time--duration',
|
3619 | buffer: '.plyr__progress__buffer',
|
3620 | loop: '.plyr__progress__loop',
|
3621 |
|
3622 | volume: '.plyr__volume--display'
|
3623 | },
|
3624 | progress: '.plyr__progress',
|
3625 | captions: '.plyr__captions',
|
3626 | caption: '.plyr__caption'
|
3627 | },
|
3628 |
|
3629 | classNames: {
|
3630 | type: 'plyr--{0}',
|
3631 | provider: 'plyr--{0}',
|
3632 | video: 'plyr__video-wrapper',
|
3633 | embed: 'plyr__video-embed',
|
3634 | videoFixedRatio: 'plyr__video-wrapper--fixed-ratio',
|
3635 | embedContainer: 'plyr__video-embed__container',
|
3636 | poster: 'plyr__poster',
|
3637 | posterEnabled: 'plyr__poster-enabled',
|
3638 | ads: 'plyr__ads',
|
3639 | control: 'plyr__control',
|
3640 | controlPressed: 'plyr__control--pressed',
|
3641 | playing: 'plyr--playing',
|
3642 | paused: 'plyr--paused',
|
3643 | stopped: 'plyr--stopped',
|
3644 | loading: 'plyr--loading',
|
3645 | hover: 'plyr--hover',
|
3646 | tooltip: 'plyr__tooltip',
|
3647 | cues: 'plyr__cues',
|
3648 | marker: 'plyr__progress__marker',
|
3649 | hidden: 'plyr__sr-only',
|
3650 | hideControls: 'plyr--hide-controls',
|
3651 | isTouch: 'plyr--is-touch',
|
3652 | uiSupported: 'plyr--full-ui',
|
3653 | noTransition: 'plyr--no-transition',
|
3654 | display: {
|
3655 | time: 'plyr__time'
|
3656 | },
|
3657 | menu: {
|
3658 | value: 'plyr__menu__value',
|
3659 | badge: 'plyr__badge',
|
3660 | open: 'plyr--menu-open'
|
3661 | },
|
3662 | captions: {
|
3663 | enabled: 'plyr--captions-enabled',
|
3664 | active: 'plyr--captions-active'
|
3665 | },
|
3666 | fullscreen: {
|
3667 | enabled: 'plyr--fullscreen-enabled',
|
3668 | fallback: 'plyr--fullscreen-fallback'
|
3669 | },
|
3670 | pip: {
|
3671 | supported: 'plyr--pip-supported',
|
3672 | active: 'plyr--pip-active'
|
3673 | },
|
3674 | airplay: {
|
3675 | supported: 'plyr--airplay-supported',
|
3676 | active: 'plyr--airplay-active'
|
3677 | },
|
3678 | previewThumbnails: {
|
3679 |
|
3680 | thumbContainer: 'plyr__preview-thumb',
|
3681 | thumbContainerShown: 'plyr__preview-thumb--is-shown',
|
3682 | imageContainer: 'plyr__preview-thumb__image-container',
|
3683 | timeContainer: 'plyr__preview-thumb__time-container',
|
3684 |
|
3685 | scrubbingContainer: 'plyr__preview-scrubbing',
|
3686 | scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown'
|
3687 | }
|
3688 | },
|
3689 |
|
3690 | attributes: {
|
3691 | embed: {
|
3692 | provider: 'data-plyr-provider',
|
3693 | id: 'data-plyr-embed-id',
|
3694 | hash: 'data-plyr-embed-hash'
|
3695 | }
|
3696 | },
|
3697 |
|
3698 |
|
3699 | ads: {
|
3700 | enabled: false,
|
3701 | publisherId: '',
|
3702 | tagUrl: ''
|
3703 | },
|
3704 |
|
3705 | previewThumbnails: {
|
3706 | enabled: false,
|
3707 | src: ''
|
3708 | },
|
3709 |
|
3710 | vimeo: {
|
3711 | byline: false,
|
3712 | portrait: false,
|
3713 | title: false,
|
3714 | speed: true,
|
3715 | transparent: false,
|
3716 |
|
3717 | customControls: true,
|
3718 | referrerPolicy: null,
|
3719 |
|
3720 |
|
3721 |
|
3722 | premium: false
|
3723 | },
|
3724 |
|
3725 | youtube: {
|
3726 | rel: 0,
|
3727 |
|
3728 | showinfo: 0,
|
3729 |
|
3730 | iv_load_policy: 3,
|
3731 |
|
3732 | modestbranding: 1,
|
3733 |
|
3734 |
|
3735 | customControls: true,
|
3736 | noCookie: false
|
3737 | },
|
3738 |
|
3739 |
|
3740 | mediaMetadata: {
|
3741 | title: '',
|
3742 | artist: '',
|
3743 | album: '',
|
3744 | artwork: []
|
3745 | },
|
3746 |
|
3747 | markers: {
|
3748 | enabled: false,
|
3749 | points: []
|
3750 | }
|
3751 | };
|
3752 |
|
3753 |
|
3754 |
|
3755 |
|
3756 |
|
3757 | const pip = {
|
3758 | active: 'picture-in-picture',
|
3759 | inactive: 'inline'
|
3760 | };
|
3761 |
|
3762 |
|
3763 |
|
3764 |
|
3765 |
|
3766 | const providers = {
|
3767 | html5: 'html5',
|
3768 | youtube: 'youtube',
|
3769 | vimeo: 'vimeo'
|
3770 | };
|
3771 | const types = {
|
3772 | audio: 'audio',
|
3773 | video: 'video'
|
3774 | };
|
3775 |
|
3776 |
|
3777 |
|
3778 |
|
3779 |
|
3780 | function getProviderByUrl(url) {
|
3781 |
|
3782 | if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(url)) {
|
3783 | return providers.youtube;
|
3784 | }
|
3785 |
|
3786 |
|
3787 | if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) {
|
3788 | return providers.vimeo;
|
3789 | }
|
3790 | return null;
|
3791 | }
|
3792 |
|
3793 |
|
3794 |
|
3795 |
|
3796 |
|
3797 | const noop = () => {};
|
3798 | class Console {
|
3799 | constructor(enabled = false) {
|
3800 | this.enabled = window.console && enabled;
|
3801 | if (this.enabled) {
|
3802 | this.log('Debugging enabled');
|
3803 | }
|
3804 | }
|
3805 | get log() {
|
3806 |
|
3807 | return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;
|
3808 | }
|
3809 | get warn() {
|
3810 |
|
3811 | return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;
|
3812 | }
|
3813 | get error() {
|
3814 |
|
3815 | return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;
|
3816 | }
|
3817 | }
|
3818 |
|
3819 | class Fullscreen {
|
3820 | constructor(player) {
|
3821 | _defineProperty$1(this, "onChange", () => {
|
3822 | if (!this.supported) return;
|
3823 |
|
3824 |
|
3825 | const button = this.player.elements.buttons.fullscreen;
|
3826 | if (is.element(button)) {
|
3827 | button.pressed = this.active;
|
3828 | }
|
3829 |
|
3830 |
|
3831 | const target = this.target === this.player.media ? this.target : this.player.elements.container;
|
3832 |
|
3833 | triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
|
3834 | });
|
3835 | _defineProperty$1(this, "toggleFallback", (toggle = false) => {
|
3836 |
|
3837 | if (toggle) {
|
3838 | this.scrollPosition = {
|
3839 | x: window.scrollX ?? 0,
|
3840 | y: window.scrollY ?? 0
|
3841 | };
|
3842 | } else {
|
3843 | window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);
|
3844 | }
|
3845 |
|
3846 |
|
3847 | document.body.style.overflow = toggle ? 'hidden' : '';
|
3848 |
|
3849 |
|
3850 | toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);
|
3851 |
|
3852 |
|
3853 | if (browser.isIos) {
|
3854 | let viewport = document.head.querySelector('meta[name="viewport"]');
|
3855 | const property = 'viewport-fit=cover';
|
3856 |
|
3857 |
|
3858 | if (!viewport) {
|
3859 | viewport = document.createElement('meta');
|
3860 | viewport.setAttribute('name', 'viewport');
|
3861 | }
|
3862 |
|
3863 |
|
3864 | const hasProperty = is.string(viewport.content) && viewport.content.includes(property);
|
3865 | if (toggle) {
|
3866 | this.cleanupViewport = !hasProperty;
|
3867 | if (!hasProperty) viewport.content += `,${property}`;
|
3868 | } else if (this.cleanupViewport) {
|
3869 | viewport.content = viewport.content.split(',').filter(part => part.trim() !== property).join(',');
|
3870 | }
|
3871 | }
|
3872 |
|
3873 |
|
3874 | this.onChange();
|
3875 | });
|
3876 |
|
3877 | _defineProperty$1(this, "trapFocus", event => {
|
3878 |
|
3879 | if (browser.isIos || browser.isIPadOS || !this.active || event.key !== 'Tab') return;
|
3880 |
|
3881 |
|
3882 | const focused = document.activeElement;
|
3883 | const focusable = getElements.call(this.player, 'a[href], button:not(:disabled), input:not(:disabled), [tabindex]');
|
3884 | const [first] = focusable;
|
3885 | const last = focusable[focusable.length - 1];
|
3886 | if (focused === last && !event.shiftKey) {
|
3887 |
|
3888 | first.focus();
|
3889 | event.preventDefault();
|
3890 | } else if (focused === first && event.shiftKey) {
|
3891 |
|
3892 | last.focus();
|
3893 | event.preventDefault();
|
3894 | }
|
3895 | });
|
3896 |
|
3897 | _defineProperty$1(this, "update", () => {
|
3898 | if (this.supported) {
|
3899 | let mode;
|
3900 | if (this.forceFallback) mode = 'Fallback (forced)';else if (Fullscreen.nativeSupported) mode = 'Native';else mode = 'Fallback';
|
3901 | this.player.debug.log(`${mode} fullscreen enabled`);
|
3902 | } else {
|
3903 | this.player.debug.log('Fullscreen not supported and fallback disabled');
|
3904 | }
|
3905 |
|
3906 |
|
3907 | toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.supported);
|
3908 | });
|
3909 |
|
3910 | _defineProperty$1(this, "enter", () => {
|
3911 | if (!this.supported) return;
|
3912 |
|
3913 |
|
3914 | if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
3915 | if (this.player.isVimeo) {
|
3916 | this.player.embed.requestFullscreen();
|
3917 | } else {
|
3918 | this.target.webkitEnterFullscreen();
|
3919 | }
|
3920 | } else if (!Fullscreen.nativeSupported || this.forceFallback) {
|
3921 | this.toggleFallback(true);
|
3922 | } else if (!this.prefix) {
|
3923 | this.target.requestFullscreen({
|
3924 | navigationUI: 'hide'
|
3925 | });
|
3926 | } else if (!is.empty(this.prefix)) {
|
3927 | this.target[`${this.prefix}Request${this.property}`]();
|
3928 | }
|
3929 | });
|
3930 |
|
3931 | _defineProperty$1(this, "exit", () => {
|
3932 | if (!this.supported) return;
|
3933 |
|
3934 |
|
3935 | if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
3936 | if (this.player.isVimeo) {
|
3937 | this.player.embed.exitFullscreen();
|
3938 | } else {
|
3939 | this.target.webkitEnterFullscreen();
|
3940 | }
|
3941 | silencePromise(this.player.play());
|
3942 | } else if (!Fullscreen.nativeSupported || this.forceFallback) {
|
3943 | this.toggleFallback(false);
|
3944 | } else if (!this.prefix) {
|
3945 | (document.cancelFullScreen || document.exitFullscreen).call(document);
|
3946 | } else if (!is.empty(this.prefix)) {
|
3947 | const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
|
3948 | document[`${this.prefix}${action}${this.property}`]();
|
3949 | }
|
3950 | });
|
3951 |
|
3952 | _defineProperty$1(this, "toggle", () => {
|
3953 | if (!this.active) this.enter();else this.exit();
|
3954 | });
|
3955 |
|
3956 | this.player = player;
|
3957 |
|
3958 |
|
3959 | this.prefix = Fullscreen.prefix;
|
3960 | this.property = Fullscreen.property;
|
3961 |
|
3962 |
|
3963 | this.scrollPosition = {
|
3964 | x: 0,
|
3965 | y: 0
|
3966 | };
|
3967 |
|
3968 |
|
3969 | this.forceFallback = player.config.fullscreen.fallback === 'force';
|
3970 |
|
3971 |
|
3972 |
|
3973 | this.player.elements.fullscreen = player.config.fullscreen.container && closest$1(this.player.elements.container, player.config.fullscreen.container);
|
3974 |
|
3975 |
|
3976 |
|
3977 | on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {
|
3978 |
|
3979 | this.onChange();
|
3980 | });
|
3981 |
|
3982 |
|
3983 | on.call(this.player, this.player.elements.container, 'dblclick', event => {
|
3984 |
|
3985 | if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {
|
3986 | return;
|
3987 | }
|
3988 | this.player.listeners.proxy(event, this.toggle, 'fullscreen');
|
3989 | });
|
3990 |
|
3991 |
|
3992 | on.call(this, this.player.elements.container, 'keydown', event => this.trapFocus(event));
|
3993 |
|
3994 |
|
3995 | this.update();
|
3996 | }
|
3997 |
|
3998 |
|
3999 | static get nativeSupported() {
|
4000 | return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled);
|
4001 | }
|
4002 |
|
4003 |
|
4004 | get useNative() {
|
4005 | return Fullscreen.nativeSupported && !this.forceFallback;
|
4006 | }
|
4007 |
|
4008 |
|
4009 | static get prefix() {
|
4010 |
|
4011 | if (is.function(document.exitFullscreen)) return '';
|
4012 |
|
4013 |
|
4014 | let value = '';
|
4015 | const prefixes = ['webkit', 'moz', 'ms'];
|
4016 | prefixes.some(pre => {
|
4017 | if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {
|
4018 | value = pre;
|
4019 | return true;
|
4020 | }
|
4021 | return false;
|
4022 | });
|
4023 | return value;
|
4024 | }
|
4025 | static get property() {
|
4026 | return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';
|
4027 | }
|
4028 |
|
4029 |
|
4030 | get supported() {
|
4031 | return [
|
4032 |
|
4033 | this.player.config.fullscreen.enabled,
|
4034 |
|
4035 | this.player.isVideo,
|
4036 |
|
4037 | Fullscreen.nativeSupported || this.player.config.fullscreen.fallback,
|
4038 |
|
4039 |
|
4040 | !this.player.isYouTube || Fullscreen.nativeSupported || !browser.isIos || this.player.config.playsinline && !this.player.config.fullscreen.iosNative].every(Boolean);
|
4041 | }
|
4042 |
|
4043 |
|
4044 | get active() {
|
4045 | if (!this.supported) return false;
|
4046 |
|
4047 |
|
4048 | if (!Fullscreen.nativeSupported || this.forceFallback) {
|
4049 | return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);
|
4050 | }
|
4051 | const element = !this.prefix ? this.target.getRootNode().fullscreenElement : this.target.getRootNode()[`${this.prefix}${this.property}Element`];
|
4052 | return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;
|
4053 | }
|
4054 |
|
4055 |
|
4056 | get target() {
|
4057 | return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.fullscreen ?? this.player.elements.container;
|
4058 | }
|
4059 | }
|
4060 |
|
4061 |
|
4062 |
|
4063 |
|
4064 |
|
4065 |
|
4066 |
|
4067 | function loadImage(src, minWidth = 1) {
|
4068 | return new Promise((resolve, reject) => {
|
4069 | const image = new Image();
|
4070 | const handler = () => {
|
4071 | delete image.onload;
|
4072 | delete image.onerror;
|
4073 | (image.naturalWidth >= minWidth ? resolve : reject)(image);
|
4074 | };
|
4075 | Object.assign(image, {
|
4076 | onload: handler,
|
4077 | onerror: handler,
|
4078 | src
|
4079 | });
|
4080 | });
|
4081 | }
|
4082 |
|
4083 |
|
4084 | const ui = {
|
4085 | addStyleHook() {
|
4086 | toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);
|
4087 | toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);
|
4088 | },
|
4089 |
|
4090 | toggleNativeControls(toggle = false) {
|
4091 | if (toggle && this.isHTML5) {
|
4092 | this.media.setAttribute('controls', '');
|
4093 | } else {
|
4094 | this.media.removeAttribute('controls');
|
4095 | }
|
4096 | },
|
4097 |
|
4098 | build() {
|
4099 |
|
4100 |
|
4101 | this.listeners.media();
|
4102 |
|
4103 |
|
4104 | if (!this.supported.ui) {
|
4105 | this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);
|
4106 |
|
4107 |
|
4108 | ui.toggleNativeControls.call(this, true);
|
4109 |
|
4110 |
|
4111 | return;
|
4112 | }
|
4113 |
|
4114 |
|
4115 | if (!is.element(this.elements.controls)) {
|
4116 |
|
4117 | controls.inject.call(this);
|
4118 |
|
4119 |
|
4120 | this.listeners.controls();
|
4121 | }
|
4122 |
|
4123 |
|
4124 | ui.toggleNativeControls.call(this);
|
4125 |
|
4126 |
|
4127 | if (this.isHTML5) {
|
4128 | captions.setup.call(this);
|
4129 | }
|
4130 |
|
4131 |
|
4132 | this.volume = null;
|
4133 |
|
4134 |
|
4135 | this.muted = null;
|
4136 |
|
4137 |
|
4138 | this.loop = null;
|
4139 |
|
4140 |
|
4141 | this.quality = null;
|
4142 |
|
4143 |
|
4144 | this.speed = null;
|
4145 |
|
4146 |
|
4147 | controls.updateVolume.call(this);
|
4148 |
|
4149 |
|
4150 | controls.timeUpdate.call(this);
|
4151 |
|
4152 |
|
4153 | controls.durationUpdate.call(this);
|
4154 |
|
4155 |
|
4156 | ui.checkPlaying.call(this);
|
4157 |
|
4158 |
|
4159 | toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo);
|
4160 |
|
4161 |
|
4162 | toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);
|
4163 |
|
4164 |
|
4165 | toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);
|
4166 |
|
4167 |
|
4168 | this.ready = true;
|
4169 |
|
4170 |
|
4171 | setTimeout(() => {
|
4172 | triggerEvent.call(this, this.media, 'ready');
|
4173 | }, 0);
|
4174 |
|
4175 |
|
4176 | ui.setTitle.call(this);
|
4177 |
|
4178 |
|
4179 | if (this.poster) {
|
4180 | ui.setPoster.call(this, this.poster, false).catch(() => {});
|
4181 | }
|
4182 |
|
4183 |
|
4184 |
|
4185 | if (this.config.duration) {
|
4186 | controls.durationUpdate.call(this);
|
4187 | }
|
4188 |
|
4189 |
|
4190 | if (this.config.mediaMetadata) {
|
4191 | controls.setMediaMetadata.call(this);
|
4192 | }
|
4193 | },
|
4194 |
|
4195 | setTitle() {
|
4196 |
|
4197 | let label = i18n.get('play', this.config);
|
4198 |
|
4199 |
|
4200 | if (is.string(this.config.title) && !is.empty(this.config.title)) {
|
4201 | label += `, ${this.config.title}`;
|
4202 | }
|
4203 |
|
4204 |
|
4205 | Array.from(this.elements.buttons.play || []).forEach(button => {
|
4206 | button.setAttribute('aria-label', label);
|
4207 | });
|
4208 |
|
4209 |
|
4210 |
|
4211 | if (this.isEmbed) {
|
4212 | const iframe = getElement.call(this, 'iframe');
|
4213 | if (!is.element(iframe)) {
|
4214 | return;
|
4215 | }
|
4216 |
|
4217 |
|
4218 | const title = !is.empty(this.config.title) ? this.config.title : 'video';
|
4219 | const format = i18n.get('frameTitle', this.config);
|
4220 | iframe.setAttribute('title', format.replace('{title}', title));
|
4221 | }
|
4222 | },
|
4223 |
|
4224 | togglePoster(enable) {
|
4225 | toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);
|
4226 | },
|
4227 |
|
4228 |
|
4229 | setPoster(poster, passive = true) {
|
4230 |
|
4231 | if (passive && this.poster) {
|
4232 | return Promise.reject(new Error('Poster already set'));
|
4233 | }
|
4234 |
|
4235 |
|
4236 | this.media.setAttribute('data-poster', poster);
|
4237 |
|
4238 |
|
4239 | this.elements.poster.removeAttribute('hidden');
|
4240 |
|
4241 |
|
4242 | return ready.call(this)
|
4243 |
|
4244 | .then(() => loadImage(poster)).catch(error => {
|
4245 |
|
4246 | if (poster === this.poster) {
|
4247 | ui.togglePoster.call(this, false);
|
4248 | }
|
4249 |
|
4250 | throw error;
|
4251 | }).then(() => {
|
4252 |
|
4253 | if (poster !== this.poster) {
|
4254 | throw new Error('setPoster cancelled by later call to setPoster');
|
4255 | }
|
4256 | }).then(() => {
|
4257 | Object.assign(this.elements.poster.style, {
|
4258 | backgroundImage: `url('${poster}')`,
|
4259 |
|
4260 | backgroundSize: ''
|
4261 | });
|
4262 | ui.togglePoster.call(this, true);
|
4263 | return poster;
|
4264 | });
|
4265 | },
|
4266 |
|
4267 | checkPlaying(event) {
|
4268 |
|
4269 | toggleClass(this.elements.container, this.config.classNames.playing, this.playing);
|
4270 | toggleClass(this.elements.container, this.config.classNames.paused, this.paused);
|
4271 | toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);
|
4272 |
|
4273 |
|
4274 | Array.from(this.elements.buttons.play || []).forEach(target => {
|
4275 | Object.assign(target, {
|
4276 | pressed: this.playing
|
4277 | });
|
4278 | target.setAttribute('aria-label', i18n.get(this.playing ? 'pause' : 'play', this.config));
|
4279 | });
|
4280 |
|
4281 |
|
4282 | if (is.event(event) && event.type === 'timeupdate') {
|
4283 | return;
|
4284 | }
|
4285 |
|
4286 |
|
4287 | ui.toggleControls.call(this);
|
4288 | },
|
4289 |
|
4290 | checkLoading(event) {
|
4291 | this.loading = ['stalled', 'waiting'].includes(event.type);
|
4292 |
|
4293 |
|
4294 | clearTimeout(this.timers.loading);
|
4295 |
|
4296 |
|
4297 | this.timers.loading = setTimeout(() => {
|
4298 |
|
4299 | toggleClass(this.elements.container, this.config.classNames.loading, this.loading);
|
4300 |
|
4301 |
|
4302 | ui.toggleControls.call(this);
|
4303 | }, this.loading ? 250 : 0);
|
4304 | },
|
4305 |
|
4306 | toggleControls(force) {
|
4307 | const {
|
4308 | controls: controlsElement
|
4309 | } = this.elements;
|
4310 | if (controlsElement && this.config.hideControls) {
|
4311 |
|
4312 | const recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now();
|
4313 |
|
4314 |
|
4315 | this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek));
|
4316 | }
|
4317 | },
|
4318 |
|
4319 | migrateStyles() {
|
4320 |
|
4321 | Object.values({
|
4322 | ...this.media.style
|
4323 | })
|
4324 |
|
4325 | .filter(key => !is.empty(key) && is.string(key) && key.startsWith('--plyr')).forEach(key => {
|
4326 |
|
4327 | this.elements.container.style.setProperty(key, this.media.style.getPropertyValue(key));
|
4328 |
|
4329 |
|
4330 | this.media.style.removeProperty(key);
|
4331 | });
|
4332 |
|
4333 |
|
4334 | if (is.empty(this.media.style)) {
|
4335 | this.media.removeAttribute('style');
|
4336 | }
|
4337 | }
|
4338 | };
|
4339 |
|
4340 | class Listeners {
|
4341 | constructor(_player) {
|
4342 |
|
4343 | _defineProperty$1(this, "firstTouch", () => {
|
4344 | const {
|
4345 | player
|
4346 | } = this;
|
4347 | const {
|
4348 | elements
|
4349 | } = player;
|
4350 | player.touch = true;
|
4351 |
|
4352 |
|
4353 | toggleClass(elements.container, player.config.classNames.isTouch, true);
|
4354 | });
|
4355 |
|
4356 | _defineProperty$1(this, "global", (toggle = true) => {
|
4357 | const {
|
4358 | player
|
4359 | } = this;
|
4360 |
|
4361 |
|
4362 | if (player.config.keyboard.global) {
|
4363 | toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);
|
4364 | }
|
4365 |
|
4366 |
|
4367 | toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle);
|
4368 |
|
4369 |
|
4370 | once.call(player, document.body, 'touchstart', this.firstTouch);
|
4371 | });
|
4372 |
|
4373 | _defineProperty$1(this, "container", () => {
|
4374 | const {
|
4375 | player
|
4376 | } = this;
|
4377 | const {
|
4378 | config,
|
4379 | elements,
|
4380 | timers
|
4381 | } = player;
|
4382 |
|
4383 |
|
4384 | if (!config.keyboard.global && config.keyboard.focused) {
|
4385 | on.call(player, elements.container, 'keydown keyup', this.handleKey, false);
|
4386 | }
|
4387 |
|
4388 |
|
4389 | on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', event => {
|
4390 | const {
|
4391 | controls: controlsElement
|
4392 | } = elements;
|
4393 |
|
4394 |
|
4395 | if (controlsElement && event.type === 'enterfullscreen') {
|
4396 | controlsElement.pressed = false;
|
4397 | controlsElement.hover = false;
|
4398 | }
|
4399 |
|
4400 |
|
4401 | const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);
|
4402 | let delay = 0;
|
4403 | if (show) {
|
4404 | ui.toggleControls.call(player, true);
|
4405 |
|
4406 | delay = player.touch ? 3000 : 2000;
|
4407 | }
|
4408 |
|
4409 |
|
4410 | clearTimeout(timers.controls);
|
4411 |
|
4412 |
|
4413 | timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);
|
4414 | });
|
4415 |
|
4416 |
|
4417 | const setGutter = () => {
|
4418 | if (!player.isVimeo || player.config.vimeo.premium) {
|
4419 | return;
|
4420 | }
|
4421 | const target = elements.wrapper;
|
4422 | const {
|
4423 | active
|
4424 | } = player.fullscreen;
|
4425 | const [videoWidth, videoHeight] = getAspectRatio.call(player);
|
4426 | const useNativeAspectRatio = supportsCSS(`aspect-ratio: ${videoWidth} / ${videoHeight}`);
|
4427 |
|
4428 |
|
4429 | if (!active) {
|
4430 | if (useNativeAspectRatio) {
|
4431 | target.style.width = null;
|
4432 | target.style.height = null;
|
4433 | } else {
|
4434 | target.style.maxWidth = null;
|
4435 | target.style.margin = null;
|
4436 | }
|
4437 | return;
|
4438 | }
|
4439 |
|
4440 |
|
4441 | const [viewportWidth, viewportHeight] = getViewportSize();
|
4442 | const overflow = viewportWidth / viewportHeight > videoWidth / videoHeight;
|
4443 | if (useNativeAspectRatio) {
|
4444 | target.style.width = overflow ? 'auto' : '100%';
|
4445 | target.style.height = overflow ? '100%' : 'auto';
|
4446 | } else {
|
4447 | target.style.maxWidth = overflow ? `${viewportHeight / videoHeight * videoWidth}px` : null;
|
4448 | target.style.margin = overflow ? '0 auto' : null;
|
4449 | }
|
4450 | };
|
4451 |
|
4452 |
|
4453 | const resized = () => {
|
4454 | clearTimeout(timers.resized);
|
4455 | timers.resized = setTimeout(setGutter, 50);
|
4456 | };
|
4457 | on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {
|
4458 | const {
|
4459 | target
|
4460 | } = player.fullscreen;
|
4461 |
|
4462 |
|
4463 | if (target !== elements.container) {
|
4464 | return;
|
4465 | }
|
4466 |
|
4467 |
|
4468 | if (!player.isEmbed && is.empty(player.config.ratio)) {
|
4469 | return;
|
4470 | }
|
4471 |
|
4472 |
|
4473 | setGutter();
|
4474 |
|
4475 |
|
4476 | const method = event.type === 'enterfullscreen' ? on : off;
|
4477 | method.call(player, window, 'resize', resized);
|
4478 | });
|
4479 | });
|
4480 |
|
4481 | _defineProperty$1(this, "media", () => {
|
4482 | const {
|
4483 | player
|
4484 | } = this;
|
4485 | const {
|
4486 | elements
|
4487 | } = player;
|
4488 |
|
4489 |
|
4490 | on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event));
|
4491 |
|
4492 |
|
4493 | on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event => controls.durationUpdate.call(player, event));
|
4494 |
|
4495 |
|
4496 | on.call(player, player.media, 'ended', () => {
|
4497 |
|
4498 | if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {
|
4499 |
|
4500 | player.restart();
|
4501 |
|
4502 |
|
4503 | player.pause();
|
4504 | }
|
4505 | });
|
4506 |
|
4507 |
|
4508 | on.call(player, player.media, 'progress playing seeking seeked', event => controls.updateProgress.call(player, event));
|
4509 |
|
4510 |
|
4511 | on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event));
|
4512 |
|
4513 |
|
4514 | on.call(player, player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(player, event));
|
4515 |
|
4516 |
|
4517 | on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event));
|
4518 |
|
4519 |
|
4520 | if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {
|
4521 |
|
4522 | const wrapper = getElement.call(player, `.${player.config.classNames.video}`);
|
4523 |
|
4524 |
|
4525 | if (!is.element(wrapper)) {
|
4526 | return;
|
4527 | }
|
4528 |
|
4529 |
|
4530 | on.call(player, elements.container, 'click', event => {
|
4531 | const targets = [elements.container, wrapper];
|
4532 |
|
4533 |
|
4534 | if (!targets.includes(event.target) && !wrapper.contains(event.target)) {
|
4535 | return;
|
4536 | }
|
4537 |
|
4538 |
|
4539 | if (player.touch && player.config.hideControls) {
|
4540 | return;
|
4541 | }
|
4542 | if (player.ended) {
|
4543 | this.proxy(event, player.restart, 'restart');
|
4544 | this.proxy(event, () => {
|
4545 | silencePromise(player.play());
|
4546 | }, 'play');
|
4547 | } else {
|
4548 | this.proxy(event, () => {
|
4549 | silencePromise(player.togglePlay());
|
4550 | }, 'play');
|
4551 | }
|
4552 | });
|
4553 | }
|
4554 |
|
4555 |
|
4556 | if (player.supported.ui && player.config.disableContextMenu) {
|
4557 | on.call(player, elements.wrapper, 'contextmenu', event => {
|
4558 | event.preventDefault();
|
4559 | }, false);
|
4560 | }
|
4561 |
|
4562 |
|
4563 | on.call(player, player.media, 'volumechange', () => {
|
4564 |
|
4565 | player.storage.set({
|
4566 | volume: player.volume,
|
4567 | muted: player.muted
|
4568 | });
|
4569 | });
|
4570 |
|
4571 |
|
4572 | on.call(player, player.media, 'ratechange', () => {
|
4573 |
|
4574 | controls.updateSetting.call(player, 'speed');
|
4575 |
|
4576 |
|
4577 | player.storage.set({
|
4578 | speed: player.speed
|
4579 | });
|
4580 | });
|
4581 |
|
4582 |
|
4583 | on.call(player, player.media, 'qualitychange', event => {
|
4584 |
|
4585 | controls.updateSetting.call(player, 'quality', null, event.detail.quality);
|
4586 | });
|
4587 |
|
4588 |
|
4589 | on.call(player, player.media, 'ready qualitychange', () => {
|
4590 | controls.setDownloadUrl.call(player);
|
4591 | });
|
4592 |
|
4593 |
|
4594 |
|
4595 | const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');
|
4596 | on.call(player, player.media, proxyEvents, event => {
|
4597 | let {
|
4598 | detail = {}
|
4599 | } = event;
|
4600 |
|
4601 |
|
4602 | if (event.type === 'error') {
|
4603 | detail = player.media.error;
|
4604 | }
|
4605 | triggerEvent.call(player, elements.container, event.type, true, detail);
|
4606 | });
|
4607 | });
|
4608 |
|
4609 | _defineProperty$1(this, "proxy", (event, defaultHandler, customHandlerKey) => {
|
4610 | const {
|
4611 | player
|
4612 | } = this;
|
4613 | const customHandler = player.config.listeners[customHandlerKey];
|
4614 | const hasCustomHandler = is.function(customHandler);
|
4615 | let returned = true;
|
4616 |
|
4617 |
|
4618 | if (hasCustomHandler) {
|
4619 | returned = customHandler.call(player, event);
|
4620 | }
|
4621 |
|
4622 |
|
4623 | if (returned !== false && is.function(defaultHandler)) {
|
4624 | defaultHandler.call(player, event);
|
4625 | }
|
4626 | });
|
4627 |
|
4628 | _defineProperty$1(this, "bind", (element, type, defaultHandler, customHandlerKey, passive = true) => {
|
4629 | const {
|
4630 | player
|
4631 | } = this;
|
4632 | const customHandler = player.config.listeners[customHandlerKey];
|
4633 | const hasCustomHandler = is.function(customHandler);
|
4634 | on.call(player, element, type, event => this.proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler);
|
4635 | });
|
4636 |
|
4637 | _defineProperty$1(this, "controls", () => {
|
4638 | const {
|
4639 | player
|
4640 | } = this;
|
4641 | const {
|
4642 | elements
|
4643 | } = player;
|
4644 |
|
4645 | const inputEvent = browser.isIE ? 'change' : 'input';
|
4646 |
|
4647 |
|
4648 | if (elements.buttons.play) {
|
4649 | Array.from(elements.buttons.play).forEach(button => {
|
4650 | this.bind(button, 'click', () => {
|
4651 | silencePromise(player.togglePlay());
|
4652 | }, 'play');
|
4653 | });
|
4654 | }
|
4655 |
|
4656 |
|
4657 | this.bind(elements.buttons.restart, 'click', player.restart, 'restart');
|
4658 |
|
4659 |
|
4660 | this.bind(elements.buttons.rewind, 'click', () => {
|
4661 |
|
4662 | player.lastSeekTime = Date.now();
|
4663 | player.rewind();
|
4664 | }, 'rewind');
|
4665 |
|
4666 |
|
4667 | this.bind(elements.buttons.fastForward, 'click', () => {
|
4668 |
|
4669 | player.lastSeekTime = Date.now();
|
4670 | player.forward();
|
4671 | }, 'fastForward');
|
4672 |
|
4673 |
|
4674 | this.bind(elements.buttons.mute, 'click', () => {
|
4675 | player.muted = !player.muted;
|
4676 | }, 'mute');
|
4677 |
|
4678 |
|
4679 | this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions());
|
4680 |
|
4681 |
|
4682 | this.bind(elements.buttons.download, 'click', () => {
|
4683 | triggerEvent.call(player, player.media, 'download');
|
4684 | }, 'download');
|
4685 |
|
4686 |
|
4687 | this.bind(elements.buttons.fullscreen, 'click', () => {
|
4688 | player.fullscreen.toggle();
|
4689 | }, 'fullscreen');
|
4690 |
|
4691 |
|
4692 | this.bind(elements.buttons.pip, 'click', () => {
|
4693 | player.pip = 'toggle';
|
4694 | }, 'pip');
|
4695 |
|
4696 |
|
4697 | this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay');
|
4698 |
|
4699 |
|
4700 | this.bind(elements.buttons.settings, 'click', event => {
|
4701 |
|
4702 | event.stopPropagation();
|
4703 | event.preventDefault();
|
4704 | controls.toggleMenu.call(player, event);
|
4705 | }, null, false);
|
4706 |
|
4707 |
|
4708 |
|
4709 |
|
4710 | this.bind(elements.buttons.settings, 'keyup', event => {
|
4711 | if (![' ', 'Enter'].includes(event.key)) {
|
4712 | return;
|
4713 | }
|
4714 |
|
4715 |
|
4716 | if (event.key === 'Enter') {
|
4717 | controls.focusFirstMenuItem.call(player, null, true);
|
4718 | return;
|
4719 | }
|
4720 |
|
4721 |
|
4722 | event.preventDefault();
|
4723 |
|
4724 |
|
4725 | event.stopPropagation();
|
4726 |
|
4727 |
|
4728 | controls.toggleMenu.call(player, event);
|
4729 | }, null, false
|
4730 | );
|
4731 |
|
4732 |
|
4733 | this.bind(elements.settings.menu, 'keydown', event => {
|
4734 | if (event.key === 'Escape') {
|
4735 | controls.toggleMenu.call(player, event);
|
4736 | }
|
4737 | });
|
4738 |
|
4739 |
|
4740 | this.bind(elements.inputs.seek, 'mousedown mousemove', event => {
|
4741 | const rect = elements.progress.getBoundingClientRect();
|
4742 | const percent = 100 / rect.width * (event.pageX - rect.left);
|
4743 | event.currentTarget.setAttribute('seek-value', percent);
|
4744 | });
|
4745 |
|
4746 |
|
4747 | this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => {
|
4748 | const seek = event.currentTarget;
|
4749 | const attribute = 'play-on-seeked';
|
4750 | if (is.keyboardEvent(event) && !['ArrowLeft', 'ArrowRight'].includes(event.key)) {
|
4751 | return;
|
4752 | }
|
4753 |
|
4754 |
|
4755 | player.lastSeekTime = Date.now();
|
4756 |
|
4757 |
|
4758 | const play = seek.hasAttribute(attribute);
|
4759 |
|
4760 | const done = ['mouseup', 'touchend', 'keyup'].includes(event.type);
|
4761 |
|
4762 |
|
4763 | if (play && done) {
|
4764 | seek.removeAttribute(attribute);
|
4765 | silencePromise(player.play());
|
4766 | } else if (!done && player.playing) {
|
4767 | seek.setAttribute(attribute, '');
|
4768 | player.pause();
|
4769 | }
|
4770 | });
|
4771 |
|
4772 |
|
4773 |
|
4774 |
|
4775 | if (browser.isIos) {
|
4776 | const inputs = getElements.call(player, 'input[type="range"]');
|
4777 | Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target)));
|
4778 | }
|
4779 |
|
4780 |
|
4781 | this.bind(elements.inputs.seek, inputEvent, event => {
|
4782 | const seek = event.currentTarget;
|
4783 |
|
4784 | let seekTo = seek.getAttribute('seek-value');
|
4785 | if (is.empty(seekTo)) {
|
4786 | seekTo = seek.value;
|
4787 | }
|
4788 | seek.removeAttribute('seek-value');
|
4789 | player.currentTime = seekTo / seek.max * player.duration;
|
4790 | }, 'seek');
|
4791 |
|
4792 |
|
4793 | this.bind(elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(player, event));
|
4794 |
|
4795 |
|
4796 |
|
4797 | this.bind(elements.progress, 'mousemove touchmove', event => {
|
4798 | const {
|
4799 | previewThumbnails
|
4800 | } = player;
|
4801 | if (previewThumbnails && previewThumbnails.loaded) {
|
4802 | previewThumbnails.startMove(event);
|
4803 | }
|
4804 | });
|
4805 |
|
4806 |
|
4807 | this.bind(elements.progress, 'mouseleave touchend click', () => {
|
4808 | const {
|
4809 | previewThumbnails
|
4810 | } = player;
|
4811 | if (previewThumbnails && previewThumbnails.loaded) {
|
4812 | previewThumbnails.endMove(false, true);
|
4813 | }
|
4814 | });
|
4815 |
|
4816 |
|
4817 | this.bind(elements.progress, 'mousedown touchstart', event => {
|
4818 | const {
|
4819 | previewThumbnails
|
4820 | } = player;
|
4821 | if (previewThumbnails && previewThumbnails.loaded) {
|
4822 | previewThumbnails.startScrubbing(event);
|
4823 | }
|
4824 | });
|
4825 | this.bind(elements.progress, 'mouseup touchend', event => {
|
4826 | const {
|
4827 | previewThumbnails
|
4828 | } = player;
|
4829 | if (previewThumbnails && previewThumbnails.loaded) {
|
4830 | previewThumbnails.endScrubbing(event);
|
4831 | }
|
4832 | });
|
4833 |
|
4834 |
|
4835 | if (browser.isWebKit) {
|
4836 | Array.from(getElements.call(player, 'input[type="range"]')).forEach(element => {
|
4837 | this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target));
|
4838 | });
|
4839 | }
|
4840 |
|
4841 |
|
4842 |
|
4843 | if (player.config.toggleInvert && !is.element(elements.display.duration)) {
|
4844 | this.bind(elements.display.currentTime, 'click', () => {
|
4845 |
|
4846 | if (player.currentTime === 0) {
|
4847 | return;
|
4848 | }
|
4849 | player.config.invertTime = !player.config.invertTime;
|
4850 | controls.timeUpdate.call(player);
|
4851 | });
|
4852 | }
|
4853 |
|
4854 |
|
4855 | this.bind(elements.inputs.volume, inputEvent, event => {
|
4856 | player.volume = event.target.value;
|
4857 | }, 'volume');
|
4858 |
|
4859 |
|
4860 | this.bind(elements.controls, 'mouseenter mouseleave', event => {
|
4861 | elements.controls.hover = !player.touch && event.type === 'mouseenter';
|
4862 | });
|
4863 |
|
4864 |
|
4865 | if (elements.fullscreen) {
|
4866 | Array.from(elements.fullscreen.children).filter(c => !c.contains(elements.container)).forEach(child => {
|
4867 | this.bind(child, 'mouseenter mouseleave', event => {
|
4868 | if (elements.controls) {
|
4869 | elements.controls.hover = !player.touch && event.type === 'mouseenter';
|
4870 | }
|
4871 | });
|
4872 | });
|
4873 | }
|
4874 |
|
4875 |
|
4876 | this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {
|
4877 | elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
|
4878 | });
|
4879 |
|
4880 |
|
4881 | this.bind(elements.controls, 'focusin', () => {
|
4882 | const {
|
4883 | config,
|
4884 | timers
|
4885 | } = player;
|
4886 |
|
4887 |
|
4888 | toggleClass(elements.controls, config.classNames.noTransition, true);
|
4889 |
|
4890 |
|
4891 | ui.toggleControls.call(player, true);
|
4892 |
|
4893 |
|
4894 | setTimeout(() => {
|
4895 | toggleClass(elements.controls, config.classNames.noTransition, false);
|
4896 | }, 0);
|
4897 |
|
4898 |
|
4899 | const delay = this.touch ? 3000 : 4000;
|
4900 |
|
4901 |
|
4902 | clearTimeout(timers.controls);
|
4903 |
|
4904 |
|
4905 | timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);
|
4906 | });
|
4907 |
|
4908 |
|
4909 | this.bind(elements.inputs.volume, 'wheel', event => {
|
4910 |
|
4911 |
|
4912 | const inverted = event.webkitDirectionInvertedFromDevice;
|
4913 |
|
4914 | const [x, y] = [event.deltaX, -event.deltaY].map(value => inverted ? -value : value);
|
4915 |
|
4916 | const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
|
4917 |
|
4918 |
|
4919 | player.increaseVolume(direction / 50);
|
4920 |
|
4921 |
|
4922 | const {
|
4923 | volume
|
4924 | } = player.media;
|
4925 | if (direction === 1 && volume < 1 || direction === -1 && volume > 0) {
|
4926 | event.preventDefault();
|
4927 | }
|
4928 | }, 'volume', false);
|
4929 | });
|
4930 | this.player = _player;
|
4931 | this.lastKey = null;
|
4932 | this.focusTimer = null;
|
4933 | this.lastKeyDown = null;
|
4934 | this.handleKey = this.handleKey.bind(this);
|
4935 | this.toggleMenu = this.toggleMenu.bind(this);
|
4936 | this.firstTouch = this.firstTouch.bind(this);
|
4937 | }
|
4938 |
|
4939 |
|
4940 | handleKey(event) {
|
4941 | const {
|
4942 | player
|
4943 | } = this;
|
4944 | const {
|
4945 | elements
|
4946 | } = player;
|
4947 | const {
|
4948 | key,
|
4949 | type,
|
4950 | altKey,
|
4951 | ctrlKey,
|
4952 | metaKey,
|
4953 | shiftKey
|
4954 | } = event;
|
4955 | const pressed = type === 'keydown';
|
4956 | const repeat = pressed && key === this.lastKey;
|
4957 |
|
4958 |
|
4959 | if (altKey || ctrlKey || metaKey || shiftKey) {
|
4960 | return;
|
4961 | }
|
4962 |
|
4963 |
|
4964 |
|
4965 | if (!key) {
|
4966 | return;
|
4967 | }
|
4968 |
|
4969 |
|
4970 | const seekByIncrement = increment => {
|
4971 |
|
4972 | player.currentTime = player.duration / 10 * increment;
|
4973 | };
|
4974 |
|
4975 |
|
4976 |
|
4977 | if (pressed) {
|
4978 |
|
4979 |
|
4980 |
|
4981 | const focused = document.activeElement;
|
4982 | if (is.element(focused)) {
|
4983 | const {
|
4984 | editable
|
4985 | } = player.config.selectors;
|
4986 | const {
|
4987 | seek
|
4988 | } = elements.inputs;
|
4989 | if (focused !== seek && matches(focused, editable)) {
|
4990 | return;
|
4991 | }
|
4992 | if (event.key === ' ' && matches(focused, 'button, [role^="menuitem"]')) {
|
4993 | return;
|
4994 | }
|
4995 | }
|
4996 |
|
4997 |
|
4998 | const preventDefault = [' ', 'ArrowLeft', 'ArrowUp', 'ArrowRight', 'ArrowDown', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'c', 'f', 'k', 'l', 'm'];
|
4999 |
|
5000 |
|
5001 | if (preventDefault.includes(key)) {
|
5002 | event.preventDefault();
|
5003 | event.stopPropagation();
|
5004 | }
|
5005 | switch (key) {
|
5006 | case '0':
|
5007 | case '1':
|
5008 | case '2':
|
5009 | case '3':
|
5010 | case '4':
|
5011 | case '5':
|
5012 | case '6':
|
5013 | case '7':
|
5014 | case '8':
|
5015 | case '9':
|
5016 | if (!repeat) {
|
5017 | seekByIncrement(parseInt(key, 10));
|
5018 | }
|
5019 | break;
|
5020 | case ' ':
|
5021 | case 'k':
|
5022 | if (!repeat) {
|
5023 | silencePromise(player.togglePlay());
|
5024 | }
|
5025 | break;
|
5026 | case 'ArrowUp':
|
5027 | player.increaseVolume(0.1);
|
5028 | break;
|
5029 | case 'ArrowDown':
|
5030 | player.decreaseVolume(0.1);
|
5031 | break;
|
5032 | case 'm':
|
5033 | if (!repeat) {
|
5034 | player.muted = !player.muted;
|
5035 | }
|
5036 | break;
|
5037 | case 'ArrowRight':
|
5038 | player.forward();
|
5039 | break;
|
5040 | case 'ArrowLeft':
|
5041 | player.rewind();
|
5042 | break;
|
5043 | case 'f':
|
5044 | player.fullscreen.toggle();
|
5045 | break;
|
5046 | case 'c':
|
5047 | if (!repeat) {
|
5048 | player.toggleCaptions();
|
5049 | }
|
5050 | break;
|
5051 | case 'l':
|
5052 | player.loop = !player.loop;
|
5053 | break;
|
5054 | }
|
5055 |
|
5056 |
|
5057 |
|
5058 | if (key === 'Escape' && !player.fullscreen.usingNative && player.fullscreen.active) {
|
5059 | player.fullscreen.toggle();
|
5060 | }
|
5061 |
|
5062 |
|
5063 | this.lastKey = key;
|
5064 | } else {
|
5065 | this.lastKey = null;
|
5066 | }
|
5067 | }
|
5068 |
|
5069 |
|
5070 | toggleMenu(event) {
|
5071 | controls.toggleMenu.call(this.player, event);
|
5072 | }
|
5073 | }
|
5074 |
|
5075 | var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
5076 |
|
5077 | function createCommonjsModule(fn, module) {
|
5078 | return module = { exports: {} }, fn(module, module.exports), module.exports;
|
5079 | }
|
5080 |
|
5081 | var loadjs_umd = createCommonjsModule(function (module, exports) {
|
5082 | (function (root, factory) {
|
5083 | {
|
5084 | module.exports = factory();
|
5085 | }
|
5086 | })(commonjsGlobal, function () {
|
5087 | |
5088 |
|
5089 |
|
5090 |
|
5091 |
|
5092 | var devnull = function () {},
|
5093 | bundleIdCache = {},
|
5094 | bundleResultCache = {},
|
5095 | bundleCallbackQueue = {};
|
5096 |
|
5097 | |
5098 |
|
5099 |
|
5100 |
|
5101 |
|
5102 | function subscribe(bundleIds, callbackFn) {
|
5103 |
|
5104 | bundleIds = bundleIds.push ? bundleIds : [bundleIds];
|
5105 | var depsNotFound = [],
|
5106 | i = bundleIds.length,
|
5107 | numWaiting = i,
|
5108 | fn,
|
5109 | bundleId,
|
5110 | r,
|
5111 | q;
|
5112 |
|
5113 |
|
5114 | fn = function (bundleId, pathsNotFound) {
|
5115 | if (pathsNotFound.length) depsNotFound.push(bundleId);
|
5116 | numWaiting--;
|
5117 | if (!numWaiting) callbackFn(depsNotFound);
|
5118 | };
|
5119 |
|
5120 |
|
5121 | while (i--) {
|
5122 | bundleId = bundleIds[i];
|
5123 |
|
5124 |
|
5125 | r = bundleResultCache[bundleId];
|
5126 | if (r) {
|
5127 | fn(bundleId, r);
|
5128 | continue;
|
5129 | }
|
5130 |
|
5131 |
|
5132 | q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];
|
5133 | q.push(fn);
|
5134 | }
|
5135 | }
|
5136 |
|
5137 | |
5138 |
|
5139 |
|
5140 |
|
5141 |
|
5142 | function publish(bundleId, pathsNotFound) {
|
5143 |
|
5144 | if (!bundleId) return;
|
5145 | var q = bundleCallbackQueue[bundleId];
|
5146 |
|
5147 |
|
5148 | bundleResultCache[bundleId] = pathsNotFound;
|
5149 |
|
5150 |
|
5151 | if (!q) return;
|
5152 |
|
5153 |
|
5154 | while (q.length) {
|
5155 | q[0](bundleId, pathsNotFound);
|
5156 | q.splice(0, 1);
|
5157 | }
|
5158 | }
|
5159 |
|
5160 | |
5161 |
|
5162 |
|
5163 |
|
5164 |
|
5165 | function executeCallbacks(args, depsNotFound) {
|
5166 |
|
5167 | if (args.call) args = {
|
5168 | success: args
|
5169 | };
|
5170 |
|
5171 |
|
5172 | if (depsNotFound.length) (args.error || devnull)(depsNotFound);else (args.success || devnull)(args);
|
5173 | }
|
5174 |
|
5175 | |
5176 |
|
5177 |
|
5178 |
|
5179 |
|
5180 | function loadFile(path, callbackFn, args, numTries) {
|
5181 | var doc = document,
|
5182 | async = args.async,
|
5183 | maxTries = (args.numRetries || 0) + 1,
|
5184 | beforeCallbackFn = args.before || devnull,
|
5185 | pathname = path.replace(/[\?|#].*$/, ''),
|
5186 | pathStripped = path.replace(/^(css|img)!/, ''),
|
5187 | isLegacyIECss,
|
5188 | e;
|
5189 | numTries = numTries || 0;
|
5190 | if (/(^css!|\.css$)/.test(pathname)) {
|
5191 |
|
5192 | e = doc.createElement('link');
|
5193 | e.rel = 'stylesheet';
|
5194 | e.href = pathStripped;
|
5195 |
|
5196 |
|
5197 | isLegacyIECss = 'hideFocus' in e;
|
5198 |
|
5199 |
|
5200 | if (isLegacyIECss && e.relList) {
|
5201 | isLegacyIECss = 0;
|
5202 | e.rel = 'preload';
|
5203 | e.as = 'style';
|
5204 | }
|
5205 | } else if (/(^img!|\.(png|gif|jpg|svg|webp)$)/.test(pathname)) {
|
5206 |
|
5207 | e = doc.createElement('img');
|
5208 | e.src = pathStripped;
|
5209 | } else {
|
5210 |
|
5211 | e = doc.createElement('script');
|
5212 | e.src = path;
|
5213 | e.async = async === undefined ? true : async;
|
5214 | }
|
5215 | e.onload = e.onerror = e.onbeforeload = function (ev) {
|
5216 | var result = ev.type[0];
|
5217 |
|
5218 |
|
5219 |
|
5220 | if (isLegacyIECss) {
|
5221 | try {
|
5222 | if (!e.sheet.cssText.length) result = 'e';
|
5223 | } catch (x) {
|
5224 |
|
5225 |
|
5226 | if (x.code != 18) result = 'e';
|
5227 | }
|
5228 | }
|
5229 |
|
5230 |
|
5231 | if (result == 'e') {
|
5232 |
|
5233 | numTries += 1;
|
5234 |
|
5235 |
|
5236 | if (numTries < maxTries) {
|
5237 | return loadFile(path, callbackFn, args, numTries);
|
5238 | }
|
5239 | } else if (e.rel == 'preload' && e.as == 'style') {
|
5240 |
|
5241 | return e.rel = 'stylesheet';
|
5242 | }
|
5243 |
|
5244 |
|
5245 | callbackFn(path, result, ev.defaultPrevented);
|
5246 | };
|
5247 |
|
5248 |
|
5249 | if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);
|
5250 | }
|
5251 |
|
5252 | |
5253 |
|
5254 |
|
5255 |
|
5256 |
|
5257 | function loadFiles(paths, callbackFn, args) {
|
5258 |
|
5259 | paths = paths.push ? paths : [paths];
|
5260 | var numWaiting = paths.length,
|
5261 | x = numWaiting,
|
5262 | pathsNotFound = [],
|
5263 | fn,
|
5264 | i;
|
5265 |
|
5266 |
|
5267 | fn = function (path, result, defaultPrevented) {
|
5268 |
|
5269 | if (result == 'e') pathsNotFound.push(path);
|
5270 |
|
5271 |
|
5272 |
|
5273 | if (result == 'b') {
|
5274 | if (defaultPrevented) pathsNotFound.push(path);else return;
|
5275 | }
|
5276 | numWaiting--;
|
5277 | if (!numWaiting) callbackFn(pathsNotFound);
|
5278 | };
|
5279 |
|
5280 |
|
5281 | for (i = 0; i < x; i++) loadFile(paths[i], fn, args);
|
5282 | }
|
5283 |
|
5284 | |
5285 |
|
5286 |
|
5287 |
|
5288 |
|
5289 |
|
5290 |
|
5291 |
|
5292 |
|
5293 | function loadjs(paths, arg1, arg2) {
|
5294 | var bundleId, args;
|
5295 |
|
5296 |
|
5297 | if (arg1 && arg1.trim) bundleId = arg1;
|
5298 |
|
5299 |
|
5300 | args = (bundleId ? arg2 : arg1) || {};
|
5301 |
|
5302 |
|
5303 | if (bundleId) {
|
5304 | if (bundleId in bundleIdCache) {
|
5305 | throw "LoadJS";
|
5306 | } else {
|
5307 | bundleIdCache[bundleId] = true;
|
5308 | }
|
5309 | }
|
5310 | function loadFn(resolve, reject) {
|
5311 | loadFiles(paths, function (pathsNotFound) {
|
5312 |
|
5313 | executeCallbacks(args, pathsNotFound);
|
5314 |
|
5315 |
|
5316 | if (resolve) {
|
5317 | executeCallbacks({
|
5318 | success: resolve,
|
5319 | error: reject
|
5320 | }, pathsNotFound);
|
5321 | }
|
5322 |
|
5323 |
|
5324 | publish(bundleId, pathsNotFound);
|
5325 | }, args);
|
5326 | }
|
5327 | if (args.returnPromise) return new Promise(loadFn);else loadFn();
|
5328 | }
|
5329 |
|
5330 | |
5331 |
|
5332 |
|
5333 |
|
5334 |
|
5335 | loadjs.ready = function ready(deps, args) {
|
5336 |
|
5337 | subscribe(deps, function (depsNotFound) {
|
5338 |
|
5339 | executeCallbacks(args, depsNotFound);
|
5340 | });
|
5341 | return loadjs;
|
5342 | };
|
5343 |
|
5344 | |
5345 |
|
5346 |
|
5347 |
|
5348 | loadjs.done = function done(bundleId) {
|
5349 | publish(bundleId, []);
|
5350 | };
|
5351 |
|
5352 | |
5353 |
|
5354 |
|
5355 | loadjs.reset = function reset() {
|
5356 | bundleIdCache = {};
|
5357 | bundleResultCache = {};
|
5358 | bundleCallbackQueue = {};
|
5359 | };
|
5360 |
|
5361 | |
5362 |
|
5363 |
|
5364 |
|
5365 | loadjs.isDefined = function isDefined(bundleId) {
|
5366 | return bundleId in bundleIdCache;
|
5367 | };
|
5368 |
|
5369 |
|
5370 | return loadjs;
|
5371 | });
|
5372 | });
|
5373 |
|
5374 |
|
5375 | function loadScript(url) {
|
5376 | return new Promise((resolve, reject) => {
|
5377 | loadjs_umd(url, {
|
5378 | success: resolve,
|
5379 | error: reject
|
5380 | });
|
5381 | });
|
5382 | }
|
5383 |
|
5384 |
|
5385 |
|
5386 |
|
5387 | function parseId$1(url) {
|
5388 | if (is.empty(url)) {
|
5389 | return null;
|
5390 | }
|
5391 | if (is.number(Number(url))) {
|
5392 | return url;
|
5393 | }
|
5394 | const regex = /^.*(vimeo.com\/|video\/)(\d+).*/;
|
5395 | return url.match(regex) ? RegExp.$2 : url;
|
5396 | }
|
5397 |
|
5398 |
|
5399 | function parseHash(url) {
|
5400 | |
5401 |
|
5402 |
|
5403 |
|
5404 |
|
5405 |
|
5406 |
|
5407 | const regex = /^.*(vimeo.com\/|video\/)(\d+)(\?.*&*h=|\/)+([\d,a-f]+)/;
|
5408 | const found = url.match(regex);
|
5409 | return found && found.length === 5 ? found[4] : null;
|
5410 | }
|
5411 |
|
5412 |
|
5413 | function assurePlaybackState$1(play) {
|
5414 | if (play && !this.embed.hasPlayed) {
|
5415 | this.embed.hasPlayed = true;
|
5416 | }
|
5417 | if (this.media.paused === play) {
|
5418 | this.media.paused = !play;
|
5419 | triggerEvent.call(this, this.media, play ? 'play' : 'pause');
|
5420 | }
|
5421 | }
|
5422 | const vimeo = {
|
5423 | setup() {
|
5424 | const player = this;
|
5425 |
|
5426 |
|
5427 | toggleClass(player.elements.wrapper, player.config.classNames.embed, true);
|
5428 |
|
5429 |
|
5430 | player.options.speed = player.config.speed.options;
|
5431 |
|
5432 |
|
5433 | setAspectRatio.call(player);
|
5434 |
|
5435 |
|
5436 | if (!is.object(window.Vimeo)) {
|
5437 | loadScript(player.config.urls.vimeo.sdk).then(() => {
|
5438 | vimeo.ready.call(player);
|
5439 | }).catch(error => {
|
5440 | player.debug.warn('Vimeo SDK (player.js) failed to load', error);
|
5441 | });
|
5442 | } else {
|
5443 | vimeo.ready.call(player);
|
5444 | }
|
5445 | },
|
5446 |
|
5447 | ready() {
|
5448 | const player = this;
|
5449 | const config = player.config.vimeo;
|
5450 | const {
|
5451 | premium,
|
5452 | referrerPolicy,
|
5453 | ...frameParams
|
5454 | } = config;
|
5455 |
|
5456 | let source = player.media.getAttribute('src');
|
5457 | let hash = '';
|
5458 |
|
5459 | if (is.empty(source)) {
|
5460 | source = player.media.getAttribute(player.config.attributes.embed.id);
|
5461 |
|
5462 | hash = player.media.getAttribute(player.config.attributes.embed.hash);
|
5463 | } else {
|
5464 | hash = parseHash(source);
|
5465 | }
|
5466 | const hashParam = hash ? {
|
5467 | h: hash
|
5468 | } : {};
|
5469 |
|
5470 |
|
5471 | if (premium) {
|
5472 | Object.assign(frameParams, {
|
5473 | controls: false,
|
5474 | sidedock: false
|
5475 | });
|
5476 | }
|
5477 |
|
5478 |
|
5479 | const params = buildUrlParams({
|
5480 | loop: player.config.loop.active,
|
5481 | autoplay: player.autoplay,
|
5482 | muted: player.muted,
|
5483 | gesture: 'media',
|
5484 | playsinline: player.config.playsinline,
|
5485 |
|
5486 | ...hashParam,
|
5487 | ...frameParams
|
5488 | });
|
5489 | const id = parseId$1(source);
|
5490 |
|
5491 | const iframe = createElement('iframe');
|
5492 | const src = format(player.config.urls.vimeo.iframe, id, params);
|
5493 | iframe.setAttribute('src', src);
|
5494 | iframe.setAttribute('allowfullscreen', '');
|
5495 | iframe.setAttribute('allow', ['autoplay', 'fullscreen', 'picture-in-picture', 'encrypted-media', 'accelerometer', 'gyroscope'].join('; '));
|
5496 |
|
5497 |
|
5498 | if (!is.empty(referrerPolicy)) {
|
5499 | iframe.setAttribute('referrerPolicy', referrerPolicy);
|
5500 | }
|
5501 |
|
5502 |
|
5503 | if (premium || !config.customControls) {
|
5504 | iframe.setAttribute('data-poster', player.poster);
|
5505 | player.media = replaceElement(iframe, player.media);
|
5506 | } else {
|
5507 | const wrapper = createElement('div', {
|
5508 | class: player.config.classNames.embedContainer,
|
5509 | 'data-poster': player.poster
|
5510 | });
|
5511 | wrapper.appendChild(iframe);
|
5512 | player.media = replaceElement(wrapper, player.media);
|
5513 | }
|
5514 |
|
5515 |
|
5516 | if (!config.customControls) {
|
5517 | fetch(format(player.config.urls.vimeo.api, src)).then(response => {
|
5518 | if (is.empty(response) || !response.thumbnail_url) {
|
5519 | return;
|
5520 | }
|
5521 |
|
5522 |
|
5523 | ui.setPoster.call(player, response.thumbnail_url).catch(() => {});
|
5524 | });
|
5525 | }
|
5526 |
|
5527 |
|
5528 |
|
5529 | player.embed = new window.Vimeo.Player(iframe, {
|
5530 | autopause: player.config.autopause,
|
5531 | muted: player.muted
|
5532 | });
|
5533 | player.media.paused = true;
|
5534 | player.media.currentTime = 0;
|
5535 |
|
5536 |
|
5537 | if (player.supported.ui) {
|
5538 | player.embed.disableTextTrack();
|
5539 | }
|
5540 |
|
5541 |
|
5542 | player.media.play = () => {
|
5543 | assurePlaybackState$1.call(player, true);
|
5544 | return player.embed.play();
|
5545 | };
|
5546 | player.media.pause = () => {
|
5547 | assurePlaybackState$1.call(player, false);
|
5548 | return player.embed.pause();
|
5549 | };
|
5550 | player.media.stop = () => {
|
5551 | player.pause();
|
5552 | player.currentTime = 0;
|
5553 | };
|
5554 |
|
5555 |
|
5556 | let {
|
5557 | currentTime
|
5558 | } = player.media;
|
5559 | Object.defineProperty(player.media, 'currentTime', {
|
5560 | get() {
|
5561 | return currentTime;
|
5562 | },
|
5563 | set(time) {
|
5564 |
|
5565 |
|
5566 |
|
5567 | const {
|
5568 | embed,
|
5569 | media,
|
5570 | paused,
|
5571 | volume
|
5572 | } = player;
|
5573 | const restorePause = paused && !embed.hasPlayed;
|
5574 |
|
5575 |
|
5576 | media.seeking = true;
|
5577 | triggerEvent.call(player, media, 'seeking');
|
5578 |
|
5579 |
|
5580 | Promise.resolve(restorePause && embed.setVolume(0))
|
5581 |
|
5582 | .then(() => embed.setCurrentTime(time))
|
5583 |
|
5584 | .then(() => restorePause && embed.pause())
|
5585 |
|
5586 | .then(() => restorePause && embed.setVolume(volume)).catch(() => {
|
5587 |
|
5588 | });
|
5589 | }
|
5590 | });
|
5591 |
|
5592 |
|
5593 | let speed = player.config.speed.selected;
|
5594 | Object.defineProperty(player.media, 'playbackRate', {
|
5595 | get() {
|
5596 | return speed;
|
5597 | },
|
5598 | set(input) {
|
5599 | player.embed.setPlaybackRate(input).then(() => {
|
5600 | speed = input;
|
5601 | triggerEvent.call(player, player.media, 'ratechange');
|
5602 | }).catch(() => {
|
5603 |
|
5604 | player.options.speed = [1];
|
5605 | });
|
5606 | }
|
5607 | });
|
5608 |
|
5609 |
|
5610 | let {
|
5611 | volume
|
5612 | } = player.config;
|
5613 | Object.defineProperty(player.media, 'volume', {
|
5614 | get() {
|
5615 | return volume;
|
5616 | },
|
5617 | set(input) {
|
5618 | player.embed.setVolume(input).then(() => {
|
5619 | volume = input;
|
5620 | triggerEvent.call(player, player.media, 'volumechange');
|
5621 | });
|
5622 | }
|
5623 | });
|
5624 |
|
5625 |
|
5626 | let {
|
5627 | muted
|
5628 | } = player.config;
|
5629 | Object.defineProperty(player.media, 'muted', {
|
5630 | get() {
|
5631 | return muted;
|
5632 | },
|
5633 | set(input) {
|
5634 | const toggle = is.boolean(input) ? input : false;
|
5635 | player.embed.setMuted(toggle ? true : player.config.muted).then(() => {
|
5636 | muted = toggle;
|
5637 | triggerEvent.call(player, player.media, 'volumechange');
|
5638 | });
|
5639 | }
|
5640 | });
|
5641 |
|
5642 |
|
5643 | let {
|
5644 | loop
|
5645 | } = player.config;
|
5646 | Object.defineProperty(player.media, 'loop', {
|
5647 | get() {
|
5648 | return loop;
|
5649 | },
|
5650 | set(input) {
|
5651 | const toggle = is.boolean(input) ? input : player.config.loop.active;
|
5652 | player.embed.setLoop(toggle).then(() => {
|
5653 | loop = toggle;
|
5654 | });
|
5655 | }
|
5656 | });
|
5657 |
|
5658 |
|
5659 | let currentSrc;
|
5660 | player.embed.getVideoUrl().then(value => {
|
5661 | currentSrc = value;
|
5662 | controls.setDownloadUrl.call(player);
|
5663 | }).catch(error => {
|
5664 | this.debug.warn(error);
|
5665 | });
|
5666 | Object.defineProperty(player.media, 'currentSrc', {
|
5667 | get() {
|
5668 | return currentSrc;
|
5669 | }
|
5670 | });
|
5671 |
|
5672 |
|
5673 | Object.defineProperty(player.media, 'ended', {
|
5674 | get() {
|
5675 | return player.currentTime === player.duration;
|
5676 | }
|
5677 | });
|
5678 |
|
5679 |
|
5680 | Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {
|
5681 | const [width, height] = dimensions;
|
5682 | player.embed.ratio = roundAspectRatio(width, height);
|
5683 | setAspectRatio.call(this);
|
5684 | });
|
5685 |
|
5686 |
|
5687 | player.embed.setAutopause(player.config.autopause).then(state => {
|
5688 | player.config.autopause = state;
|
5689 | });
|
5690 |
|
5691 |
|
5692 | player.embed.getVideoTitle().then(title => {
|
5693 | player.config.title = title;
|
5694 | ui.setTitle.call(this);
|
5695 | });
|
5696 |
|
5697 |
|
5698 | player.embed.getCurrentTime().then(value => {
|
5699 | currentTime = value;
|
5700 | triggerEvent.call(player, player.media, 'timeupdate');
|
5701 | });
|
5702 |
|
5703 |
|
5704 | player.embed.getDuration().then(value => {
|
5705 | player.media.duration = value;
|
5706 | triggerEvent.call(player, player.media, 'durationchange');
|
5707 | });
|
5708 |
|
5709 |
|
5710 | player.embed.getTextTracks().then(tracks => {
|
5711 | player.media.textTracks = tracks;
|
5712 | captions.setup.call(player);
|
5713 | });
|
5714 | player.embed.on('cuechange', ({
|
5715 | cues = []
|
5716 | }) => {
|
5717 | const strippedCues = cues.map(cue => stripHTML(cue.text));
|
5718 | captions.updateCues.call(player, strippedCues);
|
5719 | });
|
5720 | player.embed.on('loaded', () => {
|
5721 |
|
5722 | player.embed.getPaused().then(paused => {
|
5723 | assurePlaybackState$1.call(player, !paused);
|
5724 | if (!paused) {
|
5725 | triggerEvent.call(player, player.media, 'playing');
|
5726 | }
|
5727 | });
|
5728 | if (is.element(player.embed.element) && player.supported.ui) {
|
5729 | const frame = player.embed.element;
|
5730 |
|
5731 |
|
5732 |
|
5733 | frame.setAttribute('tabindex', -1);
|
5734 | }
|
5735 | });
|
5736 | player.embed.on('bufferstart', () => {
|
5737 | triggerEvent.call(player, player.media, 'waiting');
|
5738 | });
|
5739 | player.embed.on('bufferend', () => {
|
5740 | triggerEvent.call(player, player.media, 'playing');
|
5741 | });
|
5742 | player.embed.on('play', () => {
|
5743 | assurePlaybackState$1.call(player, true);
|
5744 | triggerEvent.call(player, player.media, 'playing');
|
5745 | });
|
5746 | player.embed.on('pause', () => {
|
5747 | assurePlaybackState$1.call(player, false);
|
5748 | });
|
5749 | player.embed.on('timeupdate', data => {
|
5750 | player.media.seeking = false;
|
5751 | currentTime = data.seconds;
|
5752 | triggerEvent.call(player, player.media, 'timeupdate');
|
5753 | });
|
5754 | player.embed.on('progress', data => {
|
5755 | player.media.buffered = data.percent;
|
5756 | triggerEvent.call(player, player.media, 'progress');
|
5757 |
|
5758 |
|
5759 | if (parseInt(data.percent, 10) === 1) {
|
5760 | triggerEvent.call(player, player.media, 'canplaythrough');
|
5761 | }
|
5762 |
|
5763 |
|
5764 |
|
5765 | player.embed.getDuration().then(value => {
|
5766 | if (value !== player.media.duration) {
|
5767 | player.media.duration = value;
|
5768 | triggerEvent.call(player, player.media, 'durationchange');
|
5769 | }
|
5770 | });
|
5771 | });
|
5772 | player.embed.on('seeked', () => {
|
5773 | player.media.seeking = false;
|
5774 | triggerEvent.call(player, player.media, 'seeked');
|
5775 | });
|
5776 | player.embed.on('ended', () => {
|
5777 | player.media.paused = true;
|
5778 | triggerEvent.call(player, player.media, 'ended');
|
5779 | });
|
5780 | player.embed.on('error', detail => {
|
5781 | player.media.error = detail;
|
5782 | triggerEvent.call(player, player.media, 'error');
|
5783 | });
|
5784 |
|
5785 |
|
5786 | if (config.customControls) {
|
5787 | setTimeout(() => ui.build.call(player), 0);
|
5788 | }
|
5789 | }
|
5790 | };
|
5791 |
|
5792 |
|
5793 |
|
5794 |
|
5795 | function parseId(url) {
|
5796 | if (is.empty(url)) {
|
5797 | return null;
|
5798 | }
|
5799 | const regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/;
|
5800 | return url.match(regex) ? RegExp.$2 : url;
|
5801 | }
|
5802 |
|
5803 |
|
5804 | function assurePlaybackState(play) {
|
5805 | if (play && !this.embed.hasPlayed) {
|
5806 | this.embed.hasPlayed = true;
|
5807 | }
|
5808 | if (this.media.paused === play) {
|
5809 | this.media.paused = !play;
|
5810 | triggerEvent.call(this, this.media, play ? 'play' : 'pause');
|
5811 | }
|
5812 | }
|
5813 | function getHost(config) {
|
5814 | if (config.noCookie) {
|
5815 | return 'https://www.youtube-nocookie.com';
|
5816 | }
|
5817 | if (window.location.protocol === 'http:') {
|
5818 | return 'http://www.youtube.com';
|
5819 | }
|
5820 |
|
5821 |
|
5822 | return undefined;
|
5823 | }
|
5824 | const youtube = {
|
5825 | setup() {
|
5826 |
|
5827 | toggleClass(this.elements.wrapper, this.config.classNames.embed, true);
|
5828 |
|
5829 |
|
5830 | if (is.object(window.YT) && is.function(window.YT.Player)) {
|
5831 | youtube.ready.call(this);
|
5832 | } else {
|
5833 |
|
5834 | const callback = window.onYouTubeIframeAPIReady;
|
5835 |
|
5836 |
|
5837 | window.onYouTubeIframeAPIReady = () => {
|
5838 |
|
5839 | if (is.function(callback)) {
|
5840 | callback();
|
5841 | }
|
5842 | youtube.ready.call(this);
|
5843 | };
|
5844 |
|
5845 |
|
5846 | loadScript(this.config.urls.youtube.sdk).catch(error => {
|
5847 | this.debug.warn('YouTube API failed to load', error);
|
5848 | });
|
5849 | }
|
5850 | },
|
5851 |
|
5852 | getTitle(videoId) {
|
5853 | const url = format(this.config.urls.youtube.api, videoId);
|
5854 | fetch(url).then(data => {
|
5855 | if (is.object(data)) {
|
5856 | const {
|
5857 | title,
|
5858 | height,
|
5859 | width
|
5860 | } = data;
|
5861 |
|
5862 |
|
5863 | this.config.title = title;
|
5864 | ui.setTitle.call(this);
|
5865 |
|
5866 |
|
5867 | this.embed.ratio = roundAspectRatio(width, height);
|
5868 | }
|
5869 | setAspectRatio.call(this);
|
5870 | }).catch(() => {
|
5871 |
|
5872 | setAspectRatio.call(this);
|
5873 | });
|
5874 | },
|
5875 |
|
5876 | ready() {
|
5877 | const player = this;
|
5878 | const config = player.config.youtube;
|
5879 |
|
5880 | const currentId = player.media && player.media.getAttribute('id');
|
5881 | if (!is.empty(currentId) && currentId.startsWith('youtube-')) {
|
5882 | return;
|
5883 | }
|
5884 |
|
5885 |
|
5886 | let source = player.media.getAttribute('src');
|
5887 |
|
5888 |
|
5889 | if (is.empty(source)) {
|
5890 | source = player.media.getAttribute(this.config.attributes.embed.id);
|
5891 | }
|
5892 |
|
5893 |
|
5894 | const videoId = parseId(source);
|
5895 | const id = generateId(player.provider);
|
5896 |
|
5897 | const container = createElement('div', {
|
5898 | id,
|
5899 | 'data-poster': config.customControls ? player.poster : undefined
|
5900 | });
|
5901 | player.media = replaceElement(container, player.media);
|
5902 |
|
5903 |
|
5904 | if (config.customControls) {
|
5905 | const posterSrc = s => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`;
|
5906 |
|
5907 |
|
5908 | loadImage(posterSrc('maxres'), 121)
|
5909 | .catch(() => loadImage(posterSrc('sd'), 121))
|
5910 | .catch(() => loadImage(posterSrc('hq')))
|
5911 | .then(image => ui.setPoster.call(player, image.src)).then(src => {
|
5912 |
|
5913 | if (!src.includes('maxres')) {
|
5914 | player.elements.poster.style.backgroundSize = 'cover';
|
5915 | }
|
5916 | }).catch(() => {});
|
5917 | }
|
5918 |
|
5919 |
|
5920 |
|
5921 | player.embed = new window.YT.Player(player.media, {
|
5922 | videoId,
|
5923 | host: getHost(config),
|
5924 | playerVars: extend({}, {
|
5925 |
|
5926 | autoplay: player.config.autoplay ? 1 : 0,
|
5927 |
|
5928 | hl: player.config.hl,
|
5929 |
|
5930 | controls: player.supported.ui && config.customControls ? 0 : 1,
|
5931 |
|
5932 | disablekb: 1,
|
5933 |
|
5934 | playsinline: player.config.playsinline && !player.config.fullscreen.iosNative ? 1 : 0,
|
5935 |
|
5936 | cc_load_policy: player.captions.active ? 1 : 0,
|
5937 | cc_lang_pref: player.config.captions.language,
|
5938 |
|
5939 | widget_referrer: window ? window.location.href : null
|
5940 | }, config),
|
5941 | events: {
|
5942 | onError(event) {
|
5943 |
|
5944 | if (!player.media.error) {
|
5945 | const code = event.data;
|
5946 |
|
5947 | const message = {
|
5948 | 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.',
|
5949 | 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',
|
5950 | 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.',
|
5951 | 101: 'The owner of the requested video does not allow it to be played in embedded players.',
|
5952 | 150: 'The owner of the requested video does not allow it to be played in embedded players.'
|
5953 | }[code] || 'An unknown error occurred';
|
5954 | player.media.error = {
|
5955 | code,
|
5956 | message
|
5957 | };
|
5958 | triggerEvent.call(player, player.media, 'error');
|
5959 | }
|
5960 | },
|
5961 | onPlaybackRateChange(event) {
|
5962 |
|
5963 | const instance = event.target;
|
5964 |
|
5965 |
|
5966 | player.media.playbackRate = instance.getPlaybackRate();
|
5967 | triggerEvent.call(player, player.media, 'ratechange');
|
5968 | },
|
5969 | onReady(event) {
|
5970 |
|
5971 | if (is.function(player.media.play)) {
|
5972 | return;
|
5973 | }
|
5974 |
|
5975 | const instance = event.target;
|
5976 |
|
5977 |
|
5978 | youtube.getTitle.call(player, videoId);
|
5979 |
|
5980 |
|
5981 | player.media.play = () => {
|
5982 | assurePlaybackState.call(player, true);
|
5983 | instance.playVideo();
|
5984 | };
|
5985 | player.media.pause = () => {
|
5986 | assurePlaybackState.call(player, false);
|
5987 | instance.pauseVideo();
|
5988 | };
|
5989 | player.media.stop = () => {
|
5990 | instance.stopVideo();
|
5991 | };
|
5992 | player.media.duration = instance.getDuration();
|
5993 | player.media.paused = true;
|
5994 |
|
5995 |
|
5996 | player.media.currentTime = 0;
|
5997 | Object.defineProperty(player.media, 'currentTime', {
|
5998 | get() {
|
5999 | return Number(instance.getCurrentTime());
|
6000 | },
|
6001 | set(time) {
|
6002 |
|
6003 | if (player.paused && !player.embed.hasPlayed) {
|
6004 | player.embed.mute();
|
6005 | }
|
6006 |
|
6007 |
|
6008 | player.media.seeking = true;
|
6009 | triggerEvent.call(player, player.media, 'seeking');
|
6010 |
|
6011 |
|
6012 | instance.seekTo(time);
|
6013 | }
|
6014 | });
|
6015 |
|
6016 |
|
6017 | Object.defineProperty(player.media, 'playbackRate', {
|
6018 | get() {
|
6019 | return instance.getPlaybackRate();
|
6020 | },
|
6021 | set(input) {
|
6022 | instance.setPlaybackRate(input);
|
6023 | }
|
6024 | });
|
6025 |
|
6026 |
|
6027 | let {
|
6028 | volume
|
6029 | } = player.config;
|
6030 | Object.defineProperty(player.media, 'volume', {
|
6031 | get() {
|
6032 | return volume;
|
6033 | },
|
6034 | set(input) {
|
6035 | volume = input;
|
6036 | instance.setVolume(volume * 100);
|
6037 | triggerEvent.call(player, player.media, 'volumechange');
|
6038 | }
|
6039 | });
|
6040 |
|
6041 |
|
6042 | let {
|
6043 | muted
|
6044 | } = player.config;
|
6045 | Object.defineProperty(player.media, 'muted', {
|
6046 | get() {
|
6047 | return muted;
|
6048 | },
|
6049 | set(input) {
|
6050 | const toggle = is.boolean(input) ? input : muted;
|
6051 | muted = toggle;
|
6052 | instance[toggle ? 'mute' : 'unMute']();
|
6053 | instance.setVolume(volume * 100);
|
6054 | triggerEvent.call(player, player.media, 'volumechange');
|
6055 | }
|
6056 | });
|
6057 |
|
6058 |
|
6059 | Object.defineProperty(player.media, 'currentSrc', {
|
6060 | get() {
|
6061 | return instance.getVideoUrl();
|
6062 | }
|
6063 | });
|
6064 |
|
6065 |
|
6066 | Object.defineProperty(player.media, 'ended', {
|
6067 | get() {
|
6068 | return player.currentTime === player.duration;
|
6069 | }
|
6070 | });
|
6071 |
|
6072 |
|
6073 | const speeds = instance.getAvailablePlaybackRates();
|
6074 |
|
6075 | player.options.speed = speeds.filter(s => player.config.speed.options.includes(s));
|
6076 |
|
6077 |
|
6078 | if (player.supported.ui && config.customControls) {
|
6079 | player.media.setAttribute('tabindex', -1);
|
6080 | }
|
6081 | triggerEvent.call(player, player.media, 'timeupdate');
|
6082 | triggerEvent.call(player, player.media, 'durationchange');
|
6083 |
|
6084 |
|
6085 | clearInterval(player.timers.buffering);
|
6086 |
|
6087 |
|
6088 | player.timers.buffering = setInterval(() => {
|
6089 |
|
6090 | player.media.buffered = instance.getVideoLoadedFraction();
|
6091 |
|
6092 |
|
6093 | if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {
|
6094 | triggerEvent.call(player, player.media, 'progress');
|
6095 | }
|
6096 |
|
6097 |
|
6098 | player.media.lastBuffered = player.media.buffered;
|
6099 |
|
6100 |
|
6101 | if (player.media.buffered === 1) {
|
6102 | clearInterval(player.timers.buffering);
|
6103 |
|
6104 |
|
6105 | triggerEvent.call(player, player.media, 'canplaythrough');
|
6106 | }
|
6107 | }, 200);
|
6108 |
|
6109 |
|
6110 | if (config.customControls) {
|
6111 | setTimeout(() => ui.build.call(player), 50);
|
6112 | }
|
6113 | },
|
6114 | onStateChange(event) {
|
6115 |
|
6116 | const instance = event.target;
|
6117 |
|
6118 |
|
6119 | clearInterval(player.timers.playing);
|
6120 | const seeked = player.media.seeking && [1, 2].includes(event.data);
|
6121 | if (seeked) {
|
6122 |
|
6123 | player.media.seeking = false;
|
6124 | triggerEvent.call(player, player.media, 'seeked');
|
6125 | }
|
6126 |
|
6127 |
|
6128 |
|
6129 |
|
6130 |
|
6131 |
|
6132 |
|
6133 |
|
6134 | switch (event.data) {
|
6135 | case -1:
|
6136 |
|
6137 | triggerEvent.call(player, player.media, 'timeupdate');
|
6138 |
|
6139 |
|
6140 | player.media.buffered = instance.getVideoLoadedFraction();
|
6141 | triggerEvent.call(player, player.media, 'progress');
|
6142 | break;
|
6143 | case 0:
|
6144 | assurePlaybackState.call(player, false);
|
6145 |
|
6146 |
|
6147 | if (player.media.loop) {
|
6148 |
|
6149 | instance.stopVideo();
|
6150 | instance.playVideo();
|
6151 | } else {
|
6152 | triggerEvent.call(player, player.media, 'ended');
|
6153 | }
|
6154 | break;
|
6155 | case 1:
|
6156 |
|
6157 | if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {
|
6158 | player.media.pause();
|
6159 | } else {
|
6160 | assurePlaybackState.call(player, true);
|
6161 | triggerEvent.call(player, player.media, 'playing');
|
6162 |
|
6163 |
|
6164 | player.timers.playing = setInterval(() => {
|
6165 | triggerEvent.call(player, player.media, 'timeupdate');
|
6166 | }, 50);
|
6167 |
|
6168 |
|
6169 |
|
6170 |
|
6171 | if (player.media.duration !== instance.getDuration()) {
|
6172 | player.media.duration = instance.getDuration();
|
6173 | triggerEvent.call(player, player.media, 'durationchange');
|
6174 | }
|
6175 | }
|
6176 | break;
|
6177 | case 2:
|
6178 |
|
6179 | if (!player.muted) {
|
6180 | player.embed.unMute();
|
6181 | }
|
6182 | assurePlaybackState.call(player, false);
|
6183 | break;
|
6184 | case 3:
|
6185 |
|
6186 | triggerEvent.call(player, player.media, 'waiting');
|
6187 | break;
|
6188 | }
|
6189 | triggerEvent.call(player, player.elements.container, 'statechange', false, {
|
6190 | code: event.data
|
6191 | });
|
6192 | }
|
6193 | }
|
6194 | });
|
6195 | }
|
6196 | };
|
6197 |
|
6198 |
|
6199 | const media = {
|
6200 |
|
6201 | setup() {
|
6202 |
|
6203 | if (!this.media) {
|
6204 | this.debug.warn('No media element found!');
|
6205 | return;
|
6206 | }
|
6207 |
|
6208 |
|
6209 | toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);
|
6210 |
|
6211 |
|
6212 | toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);
|
6213 |
|
6214 |
|
6215 |
|
6216 | if (this.isEmbed) {
|
6217 | toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);
|
6218 | }
|
6219 |
|
6220 |
|
6221 | if (this.isVideo) {
|
6222 |
|
6223 | this.elements.wrapper = createElement('div', {
|
6224 | class: this.config.classNames.video
|
6225 | });
|
6226 |
|
6227 |
|
6228 | wrap(this.media, this.elements.wrapper);
|
6229 |
|
6230 |
|
6231 | this.elements.poster = createElement('div', {
|
6232 | class: this.config.classNames.poster
|
6233 | });
|
6234 | this.elements.wrapper.appendChild(this.elements.poster);
|
6235 | }
|
6236 | if (this.isHTML5) {
|
6237 | html5.setup.call(this);
|
6238 | } else if (this.isYouTube) {
|
6239 | youtube.setup.call(this);
|
6240 | } else if (this.isVimeo) {
|
6241 | vimeo.setup.call(this);
|
6242 | }
|
6243 | }
|
6244 | };
|
6245 |
|
6246 | const destroy = instance => {
|
6247 |
|
6248 | if (instance.manager) {
|
6249 | instance.manager.destroy();
|
6250 | }
|
6251 |
|
6252 |
|
6253 | if (instance.elements.displayContainer) {
|
6254 | instance.elements.displayContainer.destroy();
|
6255 | }
|
6256 | instance.elements.container.remove();
|
6257 | };
|
6258 | class Ads {
|
6259 | |
6260 |
|
6261 |
|
6262 |
|
6263 |
|
6264 | constructor(player) {
|
6265 | |
6266 |
|
6267 |
|
6268 | _defineProperty$1(this, "load", () => {
|
6269 | if (!this.enabled) {
|
6270 | return;
|
6271 | }
|
6272 |
|
6273 |
|
6274 | if (!is.object(window.google) || !is.object(window.google.ima)) {
|
6275 | loadScript(this.player.config.urls.googleIMA.sdk).then(() => {
|
6276 | this.ready();
|
6277 | }).catch(() => {
|
6278 |
|
6279 | this.trigger('error', new Error('Google IMA SDK failed to load'));
|
6280 | });
|
6281 | } else {
|
6282 | this.ready();
|
6283 | }
|
6284 | });
|
6285 | |
6286 |
|
6287 |
|
6288 | _defineProperty$1(this, "ready", () => {
|
6289 |
|
6290 | if (!this.enabled) {
|
6291 | destroy(this);
|
6292 | }
|
6293 |
|
6294 |
|
6295 |
|
6296 | this.startSafetyTimer(12000, 'ready()');
|
6297 |
|
6298 |
|
6299 | this.managerPromise.then(() => {
|
6300 | this.clearSafetyTimer('onAdsManagerLoaded()');
|
6301 | });
|
6302 |
|
6303 |
|
6304 | this.listeners();
|
6305 |
|
6306 |
|
6307 | this.setupIMA();
|
6308 | });
|
6309 | |
6310 |
|
6311 |
|
6312 |
|
6313 |
|
6314 |
|
6315 |
|
6316 |
|
6317 | _defineProperty$1(this, "setupIMA", () => {
|
6318 |
|
6319 | this.elements.container = createElement('div', {
|
6320 | class: this.player.config.classNames.ads
|
6321 | });
|
6322 | this.player.elements.container.appendChild(this.elements.container);
|
6323 |
|
6324 |
|
6325 | google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);
|
6326 |
|
6327 |
|
6328 | google.ima.settings.setLocale(this.player.config.ads.language);
|
6329 |
|
6330 |
|
6331 | google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline);
|
6332 |
|
6333 |
|
6334 | this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media);
|
6335 |
|
6336 |
|
6337 | this.loader = new google.ima.AdsLoader(this.elements.displayContainer);
|
6338 |
|
6339 |
|
6340 | this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, event => this.onAdsManagerLoaded(event), false);
|
6341 | this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);
|
6342 |
|
6343 |
|
6344 | this.requestAds();
|
6345 | });
|
6346 | |
6347 |
|
6348 |
|
6349 | _defineProperty$1(this, "requestAds", () => {
|
6350 | const {
|
6351 | container
|
6352 | } = this.player.elements;
|
6353 | try {
|
6354 |
|
6355 | const request = new google.ima.AdsRequest();
|
6356 | request.adTagUrl = this.tagUrl;
|
6357 |
|
6358 |
|
6359 |
|
6360 | request.linearAdSlotWidth = container.offsetWidth;
|
6361 | request.linearAdSlotHeight = container.offsetHeight;
|
6362 | request.nonLinearAdSlotWidth = container.offsetWidth;
|
6363 | request.nonLinearAdSlotHeight = container.offsetHeight;
|
6364 |
|
6365 |
|
6366 | request.forceNonLinearFullSlot = false;
|
6367 |
|
6368 |
|
6369 | request.setAdWillPlayMuted(!this.player.muted);
|
6370 | this.loader.requestAds(request);
|
6371 | } catch (error) {
|
6372 | this.onAdError(error);
|
6373 | }
|
6374 | });
|
6375 | |
6376 |
|
6377 |
|
6378 |
|
6379 | _defineProperty$1(this, "pollCountdown", (start = false) => {
|
6380 | if (!start) {
|
6381 | clearInterval(this.countdownTimer);
|
6382 | this.elements.container.removeAttribute('data-badge-text');
|
6383 | return;
|
6384 | }
|
6385 | const update = () => {
|
6386 | const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));
|
6387 | const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;
|
6388 | this.elements.container.setAttribute('data-badge-text', label);
|
6389 | };
|
6390 | this.countdownTimer = setInterval(update, 100);
|
6391 | });
|
6392 | |
6393 |
|
6394 |
|
6395 |
|
6396 | _defineProperty$1(this, "onAdsManagerLoaded", event => {
|
6397 |
|
6398 | if (!this.enabled) {
|
6399 | return;
|
6400 | }
|
6401 |
|
6402 |
|
6403 | const settings = new google.ima.AdsRenderingSettings();
|
6404 |
|
6405 |
|
6406 | settings.restoreCustomPlaybackStateOnAdBreakComplete = true;
|
6407 | settings.enablePreloading = true;
|
6408 |
|
6409 |
|
6410 |
|
6411 | this.manager = event.getAdsManager(this.player, settings);
|
6412 |
|
6413 |
|
6414 | this.cuePoints = this.manager.getCuePoints();
|
6415 |
|
6416 |
|
6417 |
|
6418 | this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));
|
6419 |
|
6420 |
|
6421 | Object.keys(google.ima.AdEvent.Type).forEach(type => {
|
6422 | this.manager.addEventListener(google.ima.AdEvent.Type[type], e => this.onAdEvent(e));
|
6423 | });
|
6424 |
|
6425 |
|
6426 | this.trigger('loaded');
|
6427 | });
|
6428 | _defineProperty$1(this, "addCuePoints", () => {
|
6429 |
|
6430 | if (!is.empty(this.cuePoints)) {
|
6431 | this.cuePoints.forEach(cuePoint => {
|
6432 | if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {
|
6433 | const seekElement = this.player.elements.progress;
|
6434 | if (is.element(seekElement)) {
|
6435 | const cuePercentage = 100 / this.player.duration * cuePoint;
|
6436 | const cue = createElement('span', {
|
6437 | class: this.player.config.classNames.cues
|
6438 | });
|
6439 | cue.style.left = `${cuePercentage.toString()}%`;
|
6440 | seekElement.appendChild(cue);
|
6441 | }
|
6442 | }
|
6443 | });
|
6444 | }
|
6445 | });
|
6446 | |
6447 |
|
6448 |
|
6449 |
|
6450 |
|
6451 |
|
6452 | _defineProperty$1(this, "onAdEvent", event => {
|
6453 | const {
|
6454 | container
|
6455 | } = this.player.elements;
|
6456 |
|
6457 |
|
6458 | const ad = event.getAd();
|
6459 | const adData = event.getAdData();
|
6460 |
|
6461 |
|
6462 | const dispatchEvent = type => {
|
6463 | triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`);
|
6464 | };
|
6465 |
|
6466 |
|
6467 | dispatchEvent(event.type);
|
6468 | switch (event.type) {
|
6469 | case google.ima.AdEvent.Type.LOADED:
|
6470 |
|
6471 |
|
6472 | this.trigger('loaded');
|
6473 |
|
6474 |
|
6475 | this.pollCountdown(true);
|
6476 | if (!ad.isLinear()) {
|
6477 |
|
6478 | ad.width = container.offsetWidth;
|
6479 | ad.height = container.offsetHeight;
|
6480 | }
|
6481 |
|
6482 |
|
6483 |
|
6484 |
|
6485 | break;
|
6486 | case google.ima.AdEvent.Type.STARTED:
|
6487 |
|
6488 | this.manager.setVolume(this.player.volume);
|
6489 | break;
|
6490 | case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:
|
6491 |
|
6492 |
|
6493 |
|
6494 |
|
6495 |
|
6496 |
|
6497 |
|
6498 |
|
6499 |
|
6500 |
|
6501 |
|
6502 |
|
6503 |
|
6504 |
|
6505 |
|
6506 |
|
6507 |
|
6508 |
|
6509 |
|
6510 |
|
6511 |
|
6512 |
|
6513 |
|
6514 |
|
6515 |
|
6516 |
|
6517 | if (this.player.ended) {
|
6518 | this.loadAds();
|
6519 | } else {
|
6520 |
|
6521 | this.loader.contentComplete();
|
6522 | }
|
6523 | break;
|
6524 | case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:
|
6525 |
|
6526 |
|
6527 |
|
6528 |
|
6529 | this.pauseContent();
|
6530 | break;
|
6531 | case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:
|
6532 |
|
6533 |
|
6534 |
|
6535 |
|
6536 |
|
6537 | this.pollCountdown();
|
6538 | this.resumeContent();
|
6539 | break;
|
6540 | case google.ima.AdEvent.Type.LOG:
|
6541 | if (adData.adError) {
|
6542 | this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);
|
6543 | }
|
6544 | break;
|
6545 | }
|
6546 | });
|
6547 | |
6548 |
|
6549 |
|
6550 |
|
6551 | _defineProperty$1(this, "onAdError", event => {
|
6552 | this.cancel();
|
6553 | this.player.debug.warn('Ads error', event);
|
6554 | });
|
6555 | |
6556 |
|
6557 |
|
6558 |
|
6559 |
|
6560 | _defineProperty$1(this, "listeners", () => {
|
6561 | const {
|
6562 | container
|
6563 | } = this.player.elements;
|
6564 | let time;
|
6565 | this.player.on('canplay', () => {
|
6566 | this.addCuePoints();
|
6567 | });
|
6568 | this.player.on('ended', () => {
|
6569 | this.loader.contentComplete();
|
6570 | });
|
6571 | this.player.on('timeupdate', () => {
|
6572 | time = this.player.currentTime;
|
6573 | });
|
6574 | this.player.on('seeked', () => {
|
6575 | const seekedTime = this.player.currentTime;
|
6576 | if (is.empty(this.cuePoints)) {
|
6577 | return;
|
6578 | }
|
6579 | this.cuePoints.forEach((cuePoint, index) => {
|
6580 | if (time < cuePoint && cuePoint < seekedTime) {
|
6581 | this.manager.discardAdBreak();
|
6582 | this.cuePoints.splice(index, 1);
|
6583 | }
|
6584 | });
|
6585 | });
|
6586 |
|
6587 |
|
6588 |
|
6589 | window.addEventListener('resize', () => {
|
6590 | if (this.manager) {
|
6591 | this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);
|
6592 | }
|
6593 | });
|
6594 | });
|
6595 | |
6596 |
|
6597 |
|
6598 | _defineProperty$1(this, "play", () => {
|
6599 | const {
|
6600 | container
|
6601 | } = this.player.elements;
|
6602 | if (!this.managerPromise) {
|
6603 | this.resumeContent();
|
6604 | }
|
6605 |
|
6606 |
|
6607 | this.managerPromise.then(() => {
|
6608 |
|
6609 | this.manager.setVolume(this.player.volume);
|
6610 |
|
6611 |
|
6612 | this.elements.displayContainer.initialize();
|
6613 | try {
|
6614 | if (!this.initialized) {
|
6615 |
|
6616 | this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);
|
6617 |
|
6618 |
|
6619 |
|
6620 | this.manager.start();
|
6621 | }
|
6622 | this.initialized = true;
|
6623 | } catch (adError) {
|
6624 |
|
6625 |
|
6626 | this.onAdError(adError);
|
6627 | }
|
6628 | }).catch(() => {});
|
6629 | });
|
6630 | |
6631 |
|
6632 |
|
6633 | _defineProperty$1(this, "resumeContent", () => {
|
6634 |
|
6635 | this.elements.container.style.zIndex = '';
|
6636 |
|
6637 |
|
6638 | this.playing = false;
|
6639 |
|
6640 |
|
6641 | silencePromise(this.player.media.play());
|
6642 | });
|
6643 | |
6644 |
|
6645 |
|
6646 | _defineProperty$1(this, "pauseContent", () => {
|
6647 |
|
6648 | this.elements.container.style.zIndex = 3;
|
6649 |
|
6650 |
|
6651 | this.playing = true;
|
6652 |
|
6653 |
|
6654 | this.player.media.pause();
|
6655 | });
|
6656 | |
6657 |
|
6658 |
|
6659 |
|
6660 |
|
6661 |
|
6662 | _defineProperty$1(this, "cancel", () => {
|
6663 |
|
6664 | if (this.initialized) {
|
6665 | this.resumeContent();
|
6666 | }
|
6667 |
|
6668 |
|
6669 | this.trigger('error');
|
6670 |
|
6671 |
|
6672 | this.loadAds();
|
6673 | });
|
6674 | |
6675 |
|
6676 |
|
6677 | _defineProperty$1(this, "loadAds", () => {
|
6678 |
|
6679 | this.managerPromise.then(() => {
|
6680 |
|
6681 | if (this.manager) {
|
6682 | this.manager.destroy();
|
6683 | }
|
6684 |
|
6685 |
|
6686 | this.managerPromise = new Promise(resolve => {
|
6687 | this.on('loaded', resolve);
|
6688 | this.player.debug.log(this.manager);
|
6689 | });
|
6690 |
|
6691 | this.initialized = false;
|
6692 |
|
6693 |
|
6694 | this.requestAds();
|
6695 | }).catch(() => {});
|
6696 | });
|
6697 | |
6698 |
|
6699 |
|
6700 |
|
6701 |
|
6702 | _defineProperty$1(this, "trigger", (event, ...args) => {
|
6703 | const handlers = this.events[event];
|
6704 | if (is.array(handlers)) {
|
6705 | handlers.forEach(handler => {
|
6706 | if (is.function(handler)) {
|
6707 | handler.apply(this, args);
|
6708 | }
|
6709 | });
|
6710 | }
|
6711 | });
|
6712 | |
6713 |
|
6714 |
|
6715 |
|
6716 |
|
6717 |
|
6718 | _defineProperty$1(this, "on", (event, callback) => {
|
6719 | if (!is.array(this.events[event])) {
|
6720 | this.events[event] = [];
|
6721 | }
|
6722 | this.events[event].push(callback);
|
6723 | return this;
|
6724 | });
|
6725 | |
6726 |
|
6727 |
|
6728 |
|
6729 |
|
6730 |
|
6731 |
|
6732 |
|
6733 | _defineProperty$1(this, "startSafetyTimer", (time, from) => {
|
6734 | this.player.debug.log(`Safety timer invoked from: ${from}`);
|
6735 | this.safetyTimer = setTimeout(() => {
|
6736 | this.cancel();
|
6737 | this.clearSafetyTimer('startSafetyTimer()');
|
6738 | }, time);
|
6739 | });
|
6740 | |
6741 |
|
6742 |
|
6743 |
|
6744 | _defineProperty$1(this, "clearSafetyTimer", from => {
|
6745 | if (!is.nullOrUndefined(this.safetyTimer)) {
|
6746 | this.player.debug.log(`Safety timer cleared from: ${from}`);
|
6747 | clearTimeout(this.safetyTimer);
|
6748 | this.safetyTimer = null;
|
6749 | }
|
6750 | });
|
6751 | this.player = player;
|
6752 | this.config = player.config.ads;
|
6753 | this.playing = false;
|
6754 | this.initialized = false;
|
6755 | this.elements = {
|
6756 | container: null,
|
6757 | displayContainer: null
|
6758 | };
|
6759 | this.manager = null;
|
6760 | this.loader = null;
|
6761 | this.cuePoints = null;
|
6762 | this.events = {};
|
6763 | this.safetyTimer = null;
|
6764 | this.countdownTimer = null;
|
6765 |
|
6766 |
|
6767 | this.managerPromise = new Promise((resolve, reject) => {
|
6768 |
|
6769 | this.on('loaded', resolve);
|
6770 |
|
6771 |
|
6772 | this.on('error', reject);
|
6773 | });
|
6774 | this.load();
|
6775 | }
|
6776 | get enabled() {
|
6777 | const {
|
6778 | config
|
6779 | } = this;
|
6780 | return this.player.isHTML5 && this.player.isVideo && config.enabled && (!is.empty(config.publisherId) || is.url(config.tagUrl));
|
6781 | }
|
6782 |
|
6783 | get tagUrl() {
|
6784 | const {
|
6785 | config
|
6786 | } = this;
|
6787 | if (is.url(config.tagUrl)) {
|
6788 | return config.tagUrl;
|
6789 | }
|
6790 | const params = {
|
6791 | AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',
|
6792 | AV_CHANNELID: '5a0458dc28a06145e4519d21',
|
6793 | AV_URL: window.location.hostname,
|
6794 | cb: Date.now(),
|
6795 | AV_WIDTH: 640,
|
6796 | AV_HEIGHT: 480,
|
6797 | AV_CDIM2: config.publisherId
|
6798 | };
|
6799 | const base = 'https://go.aniview.com/api/adserver6/vast/';
|
6800 | return `${base}?${buildUrlParams(params)}`;
|
6801 | }
|
6802 | }
|
6803 |
|
6804 |
|
6805 |
|
6806 |
|
6807 |
|
6808 |
|
6809 |
|
6810 |
|
6811 |
|
6812 |
|
6813 |
|
6814 |
|
6815 |
|
6816 | function clamp(input = 0, min = 0, max = 255) {
|
6817 | return Math.min(Math.max(input, min), max);
|
6818 | }
|
6819 |
|
6820 |
|
6821 | const parseVtt = vttDataString => {
|
6822 | const processedList = [];
|
6823 | const frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/);
|
6824 | frames.forEach(frame => {
|
6825 | const result = {};
|
6826 | const lines = frame.split(/\r\n|\n|\r/);
|
6827 | lines.forEach(line => {
|
6828 | if (!is.number(result.startTime)) {
|
6829 |
|
6830 | const matchTimes = line.match(/([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})/);
|
6831 |
|
6832 | if (matchTimes) {
|
6833 | result.startTime = Number(matchTimes[1] || 0) * 60 * 60 + Number(matchTimes[2]) * 60 + Number(matchTimes[3]) + Number(`0.${matchTimes[4]}`);
|
6834 | result.endTime = Number(matchTimes[6] || 0) * 60 * 60 + Number(matchTimes[7]) * 60 + Number(matchTimes[8]) + Number(`0.${matchTimes[9]}`);
|
6835 | }
|
6836 | } else if (!is.empty(line.trim()) && is.empty(result.text)) {
|
6837 |
|
6838 | const lineSplit = line.trim().split('#xywh=');
|
6839 | [result.text] = lineSplit;
|
6840 |
|
6841 |
|
6842 | if (lineSplit[1]) {
|
6843 | [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');
|
6844 | }
|
6845 | }
|
6846 | });
|
6847 | if (result.text) {
|
6848 | processedList.push(result);
|
6849 | }
|
6850 | });
|
6851 | return processedList;
|
6852 | };
|
6853 |
|
6854 |
|
6855 |
|
6856 |
|
6857 |
|
6858 |
|
6859 |
|
6860 |
|
6861 |
|
6862 |
|
6863 |
|
6864 |
|
6865 | const fitRatio = (ratio, outer) => {
|
6866 | const targetRatio = outer.width / outer.height;
|
6867 | const result = {};
|
6868 | if (ratio > targetRatio) {
|
6869 | result.width = outer.width;
|
6870 | result.height = 1 / ratio * outer.width;
|
6871 | } else {
|
6872 | result.height = outer.height;
|
6873 | result.width = ratio * outer.height;
|
6874 | }
|
6875 | return result;
|
6876 | };
|
6877 | class PreviewThumbnails {
|
6878 | |
6879 |
|
6880 |
|
6881 |
|
6882 |
|
6883 | constructor(player) {
|
6884 | _defineProperty$1(this, "load", () => {
|
6885 |
|
6886 | if (this.player.elements.display.seekTooltip) {
|
6887 | this.player.elements.display.seekTooltip.hidden = this.enabled;
|
6888 | }
|
6889 | if (!this.enabled) return;
|
6890 | this.getThumbnails().then(() => {
|
6891 | if (!this.enabled) {
|
6892 | return;
|
6893 | }
|
6894 |
|
6895 |
|
6896 | this.render();
|
6897 |
|
6898 |
|
6899 | this.determineContainerAutoSizing();
|
6900 |
|
6901 |
|
6902 | this.listeners();
|
6903 | this.loaded = true;
|
6904 | });
|
6905 | });
|
6906 |
|
6907 | _defineProperty$1(this, "getThumbnails", () => {
|
6908 | return new Promise(resolve => {
|
6909 | const {
|
6910 | src
|
6911 | } = this.player.config.previewThumbnails;
|
6912 | if (is.empty(src)) {
|
6913 | throw new Error('Missing previewThumbnails.src config attribute');
|
6914 | }
|
6915 |
|
6916 |
|
6917 | const sortAndResolve = () => {
|
6918 |
|
6919 | this.thumbnails.sort((x, y) => x.height - y.height);
|
6920 | this.player.debug.log('Preview thumbnails', this.thumbnails);
|
6921 | resolve();
|
6922 | };
|
6923 |
|
6924 |
|
6925 | if (is.function(src)) {
|
6926 | src(thumbnails => {
|
6927 | this.thumbnails = thumbnails;
|
6928 | sortAndResolve();
|
6929 | });
|
6930 | }
|
6931 |
|
6932 | else {
|
6933 |
|
6934 | const urls = is.string(src) ? [src] : src;
|
6935 |
|
6936 | const promises = urls.map(u => this.getThumbnail(u));
|
6937 |
|
6938 | Promise.all(promises).then(sortAndResolve);
|
6939 | }
|
6940 | });
|
6941 | });
|
6942 |
|
6943 | _defineProperty$1(this, "getThumbnail", url => {
|
6944 | return new Promise(resolve => {
|
6945 | fetch(url).then(response => {
|
6946 | const thumbnail = {
|
6947 | frames: parseVtt(response),
|
6948 | height: null,
|
6949 | urlPrefix: ''
|
6950 | };
|
6951 |
|
6952 |
|
6953 |
|
6954 |
|
6955 | if (!thumbnail.frames[0].text.startsWith('/') && !thumbnail.frames[0].text.startsWith('http://') && !thumbnail.frames[0].text.startsWith('https://')) {
|
6956 | thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);
|
6957 | }
|
6958 |
|
6959 |
|
6960 | const tempImage = new Image();
|
6961 | tempImage.onload = () => {
|
6962 | thumbnail.height = tempImage.naturalHeight;
|
6963 | thumbnail.width = tempImage.naturalWidth;
|
6964 | this.thumbnails.push(thumbnail);
|
6965 | resolve();
|
6966 | };
|
6967 | tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;
|
6968 | });
|
6969 | });
|
6970 | });
|
6971 | _defineProperty$1(this, "startMove", event => {
|
6972 | if (!this.loaded) return;
|
6973 | if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) return;
|
6974 |
|
6975 |
|
6976 | if (!this.player.media.duration) return;
|
6977 | if (event.type === 'touchmove') {
|
6978 |
|
6979 | this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);
|
6980 | } else {
|
6981 | var _this$player$config$m, _this$player$config$m2;
|
6982 |
|
6983 | const clientRect = this.player.elements.progress.getBoundingClientRect();
|
6984 | const percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
6985 | this.seekTime = this.player.media.duration * (percentage / 100);
|
6986 | if (this.seekTime < 0) {
|
6987 |
|
6988 | this.seekTime = 0;
|
6989 | }
|
6990 | if (this.seekTime > this.player.media.duration - 1) {
|
6991 |
|
6992 | this.seekTime = this.player.media.duration - 1;
|
6993 | }
|
6994 | this.mousePosX = event.pageX;
|
6995 |
|
6996 |
|
6997 | this.elements.thumb.time.innerText = formatTime(this.seekTime);
|
6998 |
|
6999 |
|
7000 | const point = (_this$player$config$m = this.player.config.markers) === null || _this$player$config$m === void 0 ? void 0 : (_this$player$config$m2 = _this$player$config$m.points) === null || _this$player$config$m2 === void 0 ? void 0 : _this$player$config$m2.find(({
|
7001 | time: t
|
7002 | }) => t === Math.round(this.seekTime));
|
7003 |
|
7004 |
|
7005 | if (point) {
|
7006 |
|
7007 | this.elements.thumb.time.insertAdjacentHTML('afterbegin', `${point.label}<br>`);
|
7008 | }
|
7009 | }
|
7010 |
|
7011 |
|
7012 | this.showImageAtCurrentTime();
|
7013 | });
|
7014 | _defineProperty$1(this, "endMove", () => {
|
7015 | this.toggleThumbContainer(false, true);
|
7016 | });
|
7017 | _defineProperty$1(this, "startScrubbing", event => {
|
7018 |
|
7019 | if (is.nullOrUndefined(event.button) || event.button === false || event.button === 0) {
|
7020 | this.mouseDown = true;
|
7021 |
|
7022 |
|
7023 | if (this.player.media.duration) {
|
7024 | this.toggleScrubbingContainer(true);
|
7025 | this.toggleThumbContainer(false, true);
|
7026 |
|
7027 |
|
7028 | this.showImageAtCurrentTime();
|
7029 | }
|
7030 | }
|
7031 | });
|
7032 | _defineProperty$1(this, "endScrubbing", () => {
|
7033 | this.mouseDown = false;
|
7034 |
|
7035 |
|
7036 | if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {
|
7037 |
|
7038 | this.toggleScrubbingContainer(false);
|
7039 | } else {
|
7040 |
|
7041 | once.call(this.player, this.player.media, 'timeupdate', () => {
|
7042 |
|
7043 | if (!this.mouseDown) {
|
7044 | this.toggleScrubbingContainer(false);
|
7045 | }
|
7046 | });
|
7047 | }
|
7048 | });
|
7049 | |
7050 |
|
7051 |
|
7052 | _defineProperty$1(this, "listeners", () => {
|
7053 |
|
7054 | this.player.on('play', () => {
|
7055 | this.toggleThumbContainer(false, true);
|
7056 | });
|
7057 | this.player.on('seeked', () => {
|
7058 | this.toggleThumbContainer(false);
|
7059 | });
|
7060 | this.player.on('timeupdate', () => {
|
7061 | this.lastTime = this.player.media.currentTime;
|
7062 | });
|
7063 | });
|
7064 | |
7065 |
|
7066 |
|
7067 | _defineProperty$1(this, "render", () => {
|
7068 |
|
7069 | this.elements.thumb.container = createElement('div', {
|
7070 | class: this.player.config.classNames.previewThumbnails.thumbContainer
|
7071 | });
|
7072 |
|
7073 |
|
7074 | this.elements.thumb.imageContainer = createElement('div', {
|
7075 | class: this.player.config.classNames.previewThumbnails.imageContainer
|
7076 | });
|
7077 | this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);
|
7078 |
|
7079 |
|
7080 | const timeContainer = createElement('div', {
|
7081 | class: this.player.config.classNames.previewThumbnails.timeContainer
|
7082 | });
|
7083 | this.elements.thumb.time = createElement('span', {}, '00:00');
|
7084 | timeContainer.appendChild(this.elements.thumb.time);
|
7085 | this.elements.thumb.imageContainer.appendChild(timeContainer);
|
7086 |
|
7087 |
|
7088 | if (is.element(this.player.elements.progress)) {
|
7089 | this.player.elements.progress.appendChild(this.elements.thumb.container);
|
7090 | }
|
7091 |
|
7092 |
|
7093 | this.elements.scrubbing.container = createElement('div', {
|
7094 | class: this.player.config.classNames.previewThumbnails.scrubbingContainer
|
7095 | });
|
7096 | this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);
|
7097 | });
|
7098 | _defineProperty$1(this, "destroy", () => {
|
7099 | if (this.elements.thumb.container) {
|
7100 | this.elements.thumb.container.remove();
|
7101 | }
|
7102 | if (this.elements.scrubbing.container) {
|
7103 | this.elements.scrubbing.container.remove();
|
7104 | }
|
7105 | });
|
7106 | _defineProperty$1(this, "showImageAtCurrentTime", () => {
|
7107 | if (this.mouseDown) {
|
7108 | this.setScrubbingContainerSize();
|
7109 | } else {
|
7110 | this.setThumbContainerSizeAndPos();
|
7111 | }
|
7112 |
|
7113 |
|
7114 |
|
7115 | const thumbNum = this.thumbnails[0].frames.findIndex(frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime);
|
7116 | const hasThumb = thumbNum >= 0;
|
7117 | let qualityIndex = 0;
|
7118 |
|
7119 |
|
7120 | if (!this.mouseDown) {
|
7121 | this.toggleThumbContainer(hasThumb);
|
7122 | }
|
7123 |
|
7124 |
|
7125 | if (!hasThumb) {
|
7126 | return;
|
7127 | }
|
7128 |
|
7129 |
|
7130 | this.thumbnails.forEach((thumbnail, index) => {
|
7131 | if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
7132 | qualityIndex = index;
|
7133 | }
|
7134 | });
|
7135 |
|
7136 |
|
7137 | if (thumbNum !== this.showingThumb) {
|
7138 | this.showingThumb = thumbNum;
|
7139 | this.loadImage(qualityIndex);
|
7140 | }
|
7141 | });
|
7142 |
|
7143 | _defineProperty$1(this, "loadImage", (qualityIndex = 0) => {
|
7144 | const thumbNum = this.showingThumb;
|
7145 | const thumbnail = this.thumbnails[qualityIndex];
|
7146 | const {
|
7147 | urlPrefix
|
7148 | } = thumbnail;
|
7149 | const frame = thumbnail.frames[thumbNum];
|
7150 | const thumbFilename = thumbnail.frames[thumbNum].text;
|
7151 | const thumbUrl = urlPrefix + thumbFilename;
|
7152 | if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {
|
7153 |
|
7154 |
|
7155 | if (this.loadingImage && this.usingSprites) {
|
7156 | this.loadingImage.onload = null;
|
7157 | }
|
7158 |
|
7159 |
|
7160 |
|
7161 |
|
7162 | const previewImage = new Image();
|
7163 | previewImage.src = thumbUrl;
|
7164 | previewImage.dataset.index = thumbNum;
|
7165 | previewImage.dataset.filename = thumbFilename;
|
7166 | this.showingThumbFilename = thumbFilename;
|
7167 | this.player.debug.log(`Loading image: ${thumbUrl}`);
|
7168 |
|
7169 |
|
7170 | previewImage.onload = () => this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
7171 | this.loadingImage = previewImage;
|
7172 | this.removeOldImages(previewImage);
|
7173 | } else {
|
7174 |
|
7175 | this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);
|
7176 | this.currentImageElement.dataset.index = thumbNum;
|
7177 | this.removeOldImages(this.currentImageElement);
|
7178 | }
|
7179 | });
|
7180 | _defineProperty$1(this, "showImage", (previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) => {
|
7181 | this.player.debug.log(`Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`);
|
7182 | this.setImageSizeAndOffset(previewImage, frame);
|
7183 | if (newImage) {
|
7184 | this.currentImageContainer.appendChild(previewImage);
|
7185 | this.currentImageElement = previewImage;
|
7186 | if (!this.loadedImages.includes(thumbFilename)) {
|
7187 | this.loadedImages.push(thumbFilename);
|
7188 | }
|
7189 | }
|
7190 |
|
7191 |
|
7192 |
|
7193 |
|
7194 | this.preloadNearby(thumbNum, true).then(this.preloadNearby(thumbNum, false)).then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));
|
7195 | });
|
7196 |
|
7197 | _defineProperty$1(this, "removeOldImages", currentImage => {
|
7198 |
|
7199 | Array.from(this.currentImageContainer.children).forEach(image => {
|
7200 | if (image.tagName.toLowerCase() !== 'img') {
|
7201 | return;
|
7202 | }
|
7203 | const removeDelay = this.usingSprites ? 500 : 1000;
|
7204 | if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
7205 |
|
7206 |
|
7207 |
|
7208 | image.dataset.deleting = true;
|
7209 |
|
7210 |
|
7211 | const {
|
7212 | currentImageContainer
|
7213 | } = this;
|
7214 | setTimeout(() => {
|
7215 | currentImageContainer.removeChild(image);
|
7216 | this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);
|
7217 | }, removeDelay);
|
7218 | }
|
7219 | });
|
7220 | });
|
7221 |
|
7222 |
|
7223 | _defineProperty$1(this, "preloadNearby", (thumbNum, forward = true) => {
|
7224 | return new Promise(resolve => {
|
7225 | setTimeout(() => {
|
7226 | const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;
|
7227 | if (this.showingThumbFilename === oldThumbFilename) {
|
7228 |
|
7229 | let thumbnailsClone;
|
7230 | if (forward) {
|
7231 | thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);
|
7232 | } else {
|
7233 | thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
7234 | }
|
7235 | let foundOne = false;
|
7236 | thumbnailsClone.forEach(frame => {
|
7237 | const newThumbFilename = frame.text;
|
7238 | if (newThumbFilename !== oldThumbFilename) {
|
7239 |
|
7240 | if (!this.loadedImages.includes(newThumbFilename)) {
|
7241 | foundOne = true;
|
7242 | this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);
|
7243 | const {
|
7244 | urlPrefix
|
7245 | } = this.thumbnails[0];
|
7246 | const thumbURL = urlPrefix + newThumbFilename;
|
7247 | const previewImage = new Image();
|
7248 | previewImage.src = thumbURL;
|
7249 | previewImage.onload = () => {
|
7250 | this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);
|
7251 | if (!this.loadedImages.includes(newThumbFilename)) this.loadedImages.push(newThumbFilename);
|
7252 |
|
7253 |
|
7254 | resolve();
|
7255 | };
|
7256 | }
|
7257 | }
|
7258 | });
|
7259 |
|
7260 |
|
7261 | if (!foundOne) {
|
7262 | resolve();
|
7263 | }
|
7264 | }
|
7265 | }, 300);
|
7266 | });
|
7267 | });
|
7268 |
|
7269 | _defineProperty$1(this, "getHigherQuality", (currentQualityIndex, previewImage, frame, thumbFilename) => {
|
7270 | if (currentQualityIndex < this.thumbnails.length - 1) {
|
7271 |
|
7272 | let previewImageHeight = previewImage.naturalHeight;
|
7273 | if (this.usingSprites) {
|
7274 | previewImageHeight = frame.h;
|
7275 | }
|
7276 | if (previewImageHeight < this.thumbContainerHeight) {
|
7277 |
|
7278 | setTimeout(() => {
|
7279 |
|
7280 | if (this.showingThumbFilename === thumbFilename) {
|
7281 | this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);
|
7282 | this.loadImage(currentQualityIndex + 1);
|
7283 | }
|
7284 | }, 300);
|
7285 | }
|
7286 | }
|
7287 | });
|
7288 | _defineProperty$1(this, "toggleThumbContainer", (toggle = false, clearShowing = false) => {
|
7289 | const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;
|
7290 | this.elements.thumb.container.classList.toggle(className, toggle);
|
7291 | if (!toggle && clearShowing) {
|
7292 | this.showingThumb = null;
|
7293 | this.showingThumbFilename = null;
|
7294 | }
|
7295 | });
|
7296 | _defineProperty$1(this, "toggleScrubbingContainer", (toggle = false) => {
|
7297 | const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;
|
7298 | this.elements.scrubbing.container.classList.toggle(className, toggle);
|
7299 | if (!toggle) {
|
7300 | this.showingThumb = null;
|
7301 | this.showingThumbFilename = null;
|
7302 | }
|
7303 | });
|
7304 | _defineProperty$1(this, "determineContainerAutoSizing", () => {
|
7305 | if (this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) {
|
7306 |
|
7307 | this.sizeSpecifiedInCSS = true;
|
7308 | }
|
7309 | });
|
7310 |
|
7311 | _defineProperty$1(this, "setThumbContainerSizeAndPos", () => {
|
7312 | const {
|
7313 | imageContainer
|
7314 | } = this.elements.thumb;
|
7315 | if (!this.sizeSpecifiedInCSS) {
|
7316 | const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);
|
7317 | imageContainer.style.height = `${this.thumbContainerHeight}px`;
|
7318 | imageContainer.style.width = `${thumbWidth}px`;
|
7319 | } else if (imageContainer.clientHeight > 20 && imageContainer.clientWidth < 20) {
|
7320 | const thumbWidth = Math.floor(imageContainer.clientHeight * this.thumbAspectRatio);
|
7321 | imageContainer.style.width = `${thumbWidth}px`;
|
7322 | } else if (imageContainer.clientHeight < 20 && imageContainer.clientWidth > 20) {
|
7323 | const thumbHeight = Math.floor(imageContainer.clientWidth / this.thumbAspectRatio);
|
7324 | imageContainer.style.height = `${thumbHeight}px`;
|
7325 | }
|
7326 | this.setThumbContainerPos();
|
7327 | });
|
7328 | _defineProperty$1(this, "setThumbContainerPos", () => {
|
7329 | const scrubberRect = this.player.elements.progress.getBoundingClientRect();
|
7330 | const containerRect = this.player.elements.container.getBoundingClientRect();
|
7331 | const {
|
7332 | container
|
7333 | } = this.elements.thumb;
|
7334 |
|
7335 | const min = containerRect.left - scrubberRect.left + 10;
|
7336 | const max = containerRect.right - scrubberRect.left - container.clientWidth - 10;
|
7337 |
|
7338 | const position = this.mousePosX - scrubberRect.left - container.clientWidth / 2;
|
7339 | const clamped = clamp(position, min, max);
|
7340 |
|
7341 |
|
7342 | container.style.left = `${clamped}px`;
|
7343 |
|
7344 |
|
7345 | container.style.setProperty('--preview-arrow-offset', `${position - clamped}px`);
|
7346 | });
|
7347 |
|
7348 | _defineProperty$1(this, "setScrubbingContainerSize", () => {
|
7349 | const {
|
7350 | width,
|
7351 | height
|
7352 | } = fitRatio(this.thumbAspectRatio, {
|
7353 | width: this.player.media.clientWidth,
|
7354 | height: this.player.media.clientHeight
|
7355 | });
|
7356 | this.elements.scrubbing.container.style.width = `${width}px`;
|
7357 | this.elements.scrubbing.container.style.height = `${height}px`;
|
7358 | });
|
7359 |
|
7360 | _defineProperty$1(this, "setImageSizeAndOffset", (previewImage, frame) => {
|
7361 | if (!this.usingSprites) return;
|
7362 |
|
7363 |
|
7364 | const multiplier = this.thumbContainerHeight / frame.h;
|
7365 |
|
7366 |
|
7367 | previewImage.style.height = `${previewImage.naturalHeight * multiplier}px`;
|
7368 |
|
7369 | previewImage.style.width = `${previewImage.naturalWidth * multiplier}px`;
|
7370 |
|
7371 | previewImage.style.left = `-${frame.x * multiplier}px`;
|
7372 |
|
7373 | previewImage.style.top = `-${frame.y * multiplier}px`;
|
7374 | });
|
7375 | this.player = player;
|
7376 | this.thumbnails = [];
|
7377 | this.loaded = false;
|
7378 | this.lastMouseMoveTime = Date.now();
|
7379 | this.mouseDown = false;
|
7380 | this.loadedImages = [];
|
7381 | this.elements = {
|
7382 | thumb: {},
|
7383 | scrubbing: {}
|
7384 | };
|
7385 | this.load();
|
7386 | }
|
7387 | get enabled() {
|
7388 | return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;
|
7389 | }
|
7390 | get currentImageContainer() {
|
7391 | return this.mouseDown ? this.elements.scrubbing.container : this.elements.thumb.imageContainer;
|
7392 | }
|
7393 | get usingSprites() {
|
7394 | return Object.keys(this.thumbnails[0].frames[0]).includes('w');
|
7395 | }
|
7396 | get thumbAspectRatio() {
|
7397 | if (this.usingSprites) {
|
7398 | return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;
|
7399 | }
|
7400 | return this.thumbnails[0].width / this.thumbnails[0].height;
|
7401 | }
|
7402 | get thumbContainerHeight() {
|
7403 | if (this.mouseDown) {
|
7404 | const {
|
7405 | height
|
7406 | } = fitRatio(this.thumbAspectRatio, {
|
7407 | width: this.player.media.clientWidth,
|
7408 | height: this.player.media.clientHeight
|
7409 | });
|
7410 | return height;
|
7411 | }
|
7412 |
|
7413 |
|
7414 | if (this.sizeSpecifiedInCSS) {
|
7415 | return this.elements.thumb.imageContainer.clientHeight;
|
7416 | }
|
7417 | return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);
|
7418 | }
|
7419 | get currentImageElement() {
|
7420 | return this.mouseDown ? this.currentScrubbingImageElement : this.currentThumbnailImageElement;
|
7421 | }
|
7422 | set currentImageElement(element) {
|
7423 | if (this.mouseDown) {
|
7424 | this.currentScrubbingImageElement = element;
|
7425 | } else {
|
7426 | this.currentThumbnailImageElement = element;
|
7427 | }
|
7428 | }
|
7429 | }
|
7430 |
|
7431 |
|
7432 | const source = {
|
7433 |
|
7434 | insertElements(type, attributes) {
|
7435 | if (is.string(attributes)) {
|
7436 | insertElement(type, this.media, {
|
7437 | src: attributes
|
7438 | });
|
7439 | } else if (is.array(attributes)) {
|
7440 | attributes.forEach(attribute => {
|
7441 | insertElement(type, this.media, attribute);
|
7442 | });
|
7443 | }
|
7444 | },
|
7445 |
|
7446 |
|
7447 | change(input) {
|
7448 | if (!getDeep(input, 'sources.length')) {
|
7449 | this.debug.warn('Invalid source format');
|
7450 | return;
|
7451 | }
|
7452 |
|
7453 |
|
7454 | html5.cancelRequests.call(this);
|
7455 |
|
7456 |
|
7457 | this.destroy.call(this, () => {
|
7458 |
|
7459 | this.options.quality = [];
|
7460 |
|
7461 |
|
7462 | removeElement(this.media);
|
7463 | this.media = null;
|
7464 |
|
7465 |
|
7466 | if (is.element(this.elements.container)) {
|
7467 | this.elements.container.removeAttribute('class');
|
7468 | }
|
7469 |
|
7470 |
|
7471 | const {
|
7472 | sources,
|
7473 | type
|
7474 | } = input;
|
7475 | const [{
|
7476 | provider = providers.html5,
|
7477 | src
|
7478 | }] = sources;
|
7479 | const tagName = provider === 'html5' ? type : 'div';
|
7480 | const attributes = provider === 'html5' ? {} : {
|
7481 | src
|
7482 | };
|
7483 | Object.assign(this, {
|
7484 | provider,
|
7485 | type,
|
7486 |
|
7487 | supported: support.check(type, provider, this.config.playsinline),
|
7488 |
|
7489 | media: createElement(tagName, attributes)
|
7490 | });
|
7491 |
|
7492 |
|
7493 | this.elements.container.appendChild(this.media);
|
7494 |
|
7495 |
|
7496 | if (is.boolean(input.autoplay)) {
|
7497 | this.config.autoplay = input.autoplay;
|
7498 | }
|
7499 |
|
7500 |
|
7501 | if (this.isHTML5) {
|
7502 | if (this.config.crossorigin) {
|
7503 | this.media.setAttribute('crossorigin', '');
|
7504 | }
|
7505 | if (this.config.autoplay) {
|
7506 | this.media.setAttribute('autoplay', '');
|
7507 | }
|
7508 | if (!is.empty(input.poster)) {
|
7509 | this.poster = input.poster;
|
7510 | }
|
7511 | if (this.config.loop.active) {
|
7512 | this.media.setAttribute('loop', '');
|
7513 | }
|
7514 | if (this.config.muted) {
|
7515 | this.media.setAttribute('muted', '');
|
7516 | }
|
7517 | if (this.config.playsinline) {
|
7518 | this.media.setAttribute('playsinline', '');
|
7519 | }
|
7520 | }
|
7521 |
|
7522 |
|
7523 | ui.addStyleHook.call(this);
|
7524 |
|
7525 |
|
7526 | if (this.isHTML5) {
|
7527 | source.insertElements.call(this, 'source', sources);
|
7528 | }
|
7529 |
|
7530 |
|
7531 | this.config.title = input.title;
|
7532 |
|
7533 |
|
7534 | media.setup.call(this);
|
7535 |
|
7536 |
|
7537 | if (this.isHTML5) {
|
7538 |
|
7539 | if (Object.keys(input).includes('tracks')) {
|
7540 | source.insertElements.call(this, 'track', input.tracks);
|
7541 | }
|
7542 | }
|
7543 |
|
7544 |
|
7545 | if (this.isHTML5 || this.isEmbed && !this.supported.ui) {
|
7546 |
|
7547 | ui.build.call(this);
|
7548 | }
|
7549 |
|
7550 |
|
7551 | if (this.isHTML5) {
|
7552 | this.media.load();
|
7553 | }
|
7554 |
|
7555 |
|
7556 | if (!is.empty(input.previewThumbnails)) {
|
7557 | Object.assign(this.config.previewThumbnails, input.previewThumbnails);
|
7558 |
|
7559 |
|
7560 | if (this.previewThumbnails && this.previewThumbnails.loaded) {
|
7561 | this.previewThumbnails.destroy();
|
7562 | this.previewThumbnails = null;
|
7563 | }
|
7564 |
|
7565 |
|
7566 | if (this.config.previewThumbnails.enabled) {
|
7567 | this.previewThumbnails = new PreviewThumbnails(this);
|
7568 | }
|
7569 | }
|
7570 |
|
7571 |
|
7572 | this.fullscreen.update();
|
7573 | }, true);
|
7574 | }
|
7575 | };
|
7576 |
|
7577 |
|
7578 |
|
7579 |
|
7580 |
|
7581 |
|
7582 | class Plyr {
|
7583 | constructor(target, options) {
|
7584 | |
7585 |
|
7586 |
|
7587 | _defineProperty$1(this, "play", () => {
|
7588 | if (!is.function(this.media.play)) {
|
7589 | return null;
|
7590 | }
|
7591 |
|
7592 |
|
7593 | if (this.ads && this.ads.enabled) {
|
7594 | this.ads.managerPromise.then(() => this.ads.play()).catch(() => silencePromise(this.media.play()));
|
7595 | }
|
7596 |
|
7597 |
|
7598 | return this.media.play();
|
7599 | });
|
7600 | |
7601 |
|
7602 |
|
7603 | _defineProperty$1(this, "pause", () => {
|
7604 | if (!this.playing || !is.function(this.media.pause)) {
|
7605 | return null;
|
7606 | }
|
7607 | return this.media.pause();
|
7608 | });
|
7609 | |
7610 |
|
7611 |
|
7612 |
|
7613 | _defineProperty$1(this, "togglePlay", input => {
|
7614 |
|
7615 | const toggle = is.boolean(input) ? input : !this.playing;
|
7616 | if (toggle) {
|
7617 | return this.play();
|
7618 | }
|
7619 | return this.pause();
|
7620 | });
|
7621 | |
7622 |
|
7623 |
|
7624 | _defineProperty$1(this, "stop", () => {
|
7625 | if (this.isHTML5) {
|
7626 | this.pause();
|
7627 | this.restart();
|
7628 | } else if (is.function(this.media.stop)) {
|
7629 | this.media.stop();
|
7630 | }
|
7631 | });
|
7632 | |
7633 |
|
7634 |
|
7635 | _defineProperty$1(this, "restart", () => {
|
7636 | this.currentTime = 0;
|
7637 | });
|
7638 | |
7639 |
|
7640 |
|
7641 |
|
7642 | _defineProperty$1(this, "rewind", seekTime => {
|
7643 | this.currentTime -= is.number(seekTime) ? seekTime : this.config.seekTime;
|
7644 | });
|
7645 | |
7646 |
|
7647 |
|
7648 |
|
7649 | _defineProperty$1(this, "forward", seekTime => {
|
7650 | this.currentTime += is.number(seekTime) ? seekTime : this.config.seekTime;
|
7651 | });
|
7652 | |
7653 |
|
7654 |
|
7655 |
|
7656 | _defineProperty$1(this, "increaseVolume", step => {
|
7657 | const volume = this.media.muted ? 0 : this.volume;
|
7658 | this.volume = volume + (is.number(step) ? step : 0);
|
7659 | });
|
7660 | |
7661 |
|
7662 |
|
7663 |
|
7664 | _defineProperty$1(this, "decreaseVolume", step => {
|
7665 | this.increaseVolume(-step);
|
7666 | });
|
7667 | |
7668 |
|
7669 |
|
7670 |
|
7671 | _defineProperty$1(this, "airplay", () => {
|
7672 |
|
7673 | if (support.airplay) {
|
7674 | this.media.webkitShowPlaybackTargetPicker();
|
7675 | }
|
7676 | });
|
7677 | |
7678 |
|
7679 |
|
7680 |
|
7681 | _defineProperty$1(this, "toggleControls", toggle => {
|
7682 |
|
7683 | if (this.supported.ui && !this.isAudio) {
|
7684 |
|
7685 | const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);
|
7686 |
|
7687 | const force = typeof toggle === 'undefined' ? undefined : !toggle;
|
7688 |
|
7689 | const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);
|
7690 |
|
7691 |
|
7692 | if (hiding && is.array(this.config.controls) && this.config.controls.includes('settings') && !is.empty(this.config.settings)) {
|
7693 | controls.toggleMenu.call(this, false);
|
7694 | }
|
7695 |
|
7696 |
|
7697 | if (hiding !== isHidden) {
|
7698 | const eventName = hiding ? 'controlshidden' : 'controlsshown';
|
7699 | triggerEvent.call(this, this.media, eventName);
|
7700 | }
|
7701 | return !hiding;
|
7702 | }
|
7703 | return false;
|
7704 | });
|
7705 | |
7706 |
|
7707 |
|
7708 |
|
7709 |
|
7710 | _defineProperty$1(this, "on", (event, callback) => {
|
7711 | on.call(this, this.elements.container, event, callback);
|
7712 | });
|
7713 | |
7714 |
|
7715 |
|
7716 |
|
7717 |
|
7718 | _defineProperty$1(this, "once", (event, callback) => {
|
7719 | once.call(this, this.elements.container, event, callback);
|
7720 | });
|
7721 | |
7722 |
|
7723 |
|
7724 |
|
7725 |
|
7726 | _defineProperty$1(this, "off", (event, callback) => {
|
7727 | off(this.elements.container, event, callback);
|
7728 | });
|
7729 | |
7730 |
|
7731 |
|
7732 |
|
7733 |
|
7734 |
|
7735 |
|
7736 | _defineProperty$1(this, "destroy", (callback, soft = false) => {
|
7737 | if (!this.ready) {
|
7738 | return;
|
7739 | }
|
7740 | const done = () => {
|
7741 |
|
7742 | document.body.style.overflow = '';
|
7743 |
|
7744 |
|
7745 | this.embed = null;
|
7746 |
|
7747 |
|
7748 | if (soft) {
|
7749 | if (Object.keys(this.elements).length) {
|
7750 |
|
7751 | removeElement(this.elements.buttons.play);
|
7752 | removeElement(this.elements.captions);
|
7753 | removeElement(this.elements.controls);
|
7754 | removeElement(this.elements.wrapper);
|
7755 |
|
7756 |
|
7757 | this.elements.buttons.play = null;
|
7758 | this.elements.captions = null;
|
7759 | this.elements.controls = null;
|
7760 | this.elements.wrapper = null;
|
7761 | }
|
7762 |
|
7763 |
|
7764 | if (is.function(callback)) {
|
7765 | callback();
|
7766 | }
|
7767 | } else {
|
7768 |
|
7769 | unbindListeners.call(this);
|
7770 |
|
7771 |
|
7772 | html5.cancelRequests.call(this);
|
7773 |
|
7774 |
|
7775 | replaceElement(this.elements.original, this.elements.container);
|
7776 |
|
7777 |
|
7778 | triggerEvent.call(this, this.elements.original, 'destroyed', true);
|
7779 |
|
7780 |
|
7781 | if (is.function(callback)) {
|
7782 | callback.call(this.elements.original);
|
7783 | }
|
7784 |
|
7785 |
|
7786 | this.ready = false;
|
7787 |
|
7788 |
|
7789 | setTimeout(() => {
|
7790 | this.elements = null;
|
7791 | this.media = null;
|
7792 | }, 200);
|
7793 | }
|
7794 | };
|
7795 |
|
7796 |
|
7797 | this.stop();
|
7798 |
|
7799 |
|
7800 | clearTimeout(this.timers.loading);
|
7801 | clearTimeout(this.timers.controls);
|
7802 | clearTimeout(this.timers.resized);
|
7803 |
|
7804 |
|
7805 | if (this.isHTML5) {
|
7806 |
|
7807 | ui.toggleNativeControls.call(this, true);
|
7808 |
|
7809 |
|
7810 | done();
|
7811 | } else if (this.isYouTube) {
|
7812 |
|
7813 | clearInterval(this.timers.buffering);
|
7814 | clearInterval(this.timers.playing);
|
7815 |
|
7816 |
|
7817 | if (this.embed !== null && is.function(this.embed.destroy)) {
|
7818 | this.embed.destroy();
|
7819 | }
|
7820 |
|
7821 |
|
7822 | done();
|
7823 | } else if (this.isVimeo) {
|
7824 |
|
7825 |
|
7826 | if (this.embed !== null) {
|
7827 | this.embed.unload().then(done);
|
7828 | }
|
7829 |
|
7830 |
|
7831 | setTimeout(done, 200);
|
7832 | }
|
7833 | });
|
7834 | |
7835 |
|
7836 |
|
7837 |
|
7838 | _defineProperty$1(this, "supports", type => support.mime.call(this, type));
|
7839 | this.timers = {};
|
7840 |
|
7841 |
|
7842 | this.ready = false;
|
7843 | this.loading = false;
|
7844 | this.failed = false;
|
7845 |
|
7846 |
|
7847 | this.touch = support.touch;
|
7848 |
|
7849 |
|
7850 | this.media = target;
|
7851 |
|
7852 |
|
7853 | if (is.string(this.media)) {
|
7854 | this.media = document.querySelectorAll(this.media);
|
7855 | }
|
7856 |
|
7857 |
|
7858 | if (window.jQuery && this.media instanceof jQuery || is.nodeList(this.media) || is.array(this.media)) {
|
7859 |
|
7860 | this.media = this.media[0];
|
7861 | }
|
7862 |
|
7863 |
|
7864 | this.config = extend({}, defaults, Plyr.defaults, options || {}, (() => {
|
7865 | try {
|
7866 | return JSON.parse(this.media.getAttribute('data-plyr-config'));
|
7867 | } catch (_) {
|
7868 | return {};
|
7869 | }
|
7870 | })());
|
7871 |
|
7872 |
|
7873 | this.elements = {
|
7874 | container: null,
|
7875 | fullscreen: null,
|
7876 | captions: null,
|
7877 | buttons: {},
|
7878 | display: {},
|
7879 | progress: {},
|
7880 | inputs: {},
|
7881 | settings: {
|
7882 | popup: null,
|
7883 | menu: null,
|
7884 | panels: {},
|
7885 | buttons: {}
|
7886 | }
|
7887 | };
|
7888 |
|
7889 |
|
7890 | this.captions = {
|
7891 | active: null,
|
7892 | currentTrack: -1,
|
7893 | meta: new WeakMap()
|
7894 | };
|
7895 |
|
7896 |
|
7897 | this.fullscreen = {
|
7898 | active: false
|
7899 | };
|
7900 |
|
7901 |
|
7902 | this.options = {
|
7903 | speed: [],
|
7904 | quality: []
|
7905 | };
|
7906 |
|
7907 |
|
7908 |
|
7909 | this.debug = new Console(this.config.debug);
|
7910 |
|
7911 |
|
7912 | this.debug.log('Config', this.config);
|
7913 | this.debug.log('Support', support);
|
7914 |
|
7915 |
|
7916 | if (is.nullOrUndefined(this.media) || !is.element(this.media)) {
|
7917 | this.debug.error('Setup failed: no suitable element passed');
|
7918 | return;
|
7919 | }
|
7920 |
|
7921 |
|
7922 | if (this.media.plyr) {
|
7923 | this.debug.warn('Target already setup');
|
7924 | return;
|
7925 | }
|
7926 |
|
7927 |
|
7928 | if (!this.config.enabled) {
|
7929 | this.debug.error('Setup failed: disabled by config');
|
7930 | return;
|
7931 | }
|
7932 |
|
7933 |
|
7934 |
|
7935 | if (!support.check().api) {
|
7936 | this.debug.error('Setup failed: no support');
|
7937 | return;
|
7938 | }
|
7939 |
|
7940 |
|
7941 | const clone = this.media.cloneNode(true);
|
7942 | clone.autoplay = false;
|
7943 | this.elements.original = clone;
|
7944 |
|
7945 |
|
7946 |
|
7947 | const _type = this.media.tagName.toLowerCase();
|
7948 |
|
7949 | let iframe = null;
|
7950 | let url = null;
|
7951 |
|
7952 |
|
7953 | switch (_type) {
|
7954 | case 'div':
|
7955 |
|
7956 | iframe = this.media.querySelector('iframe');
|
7957 |
|
7958 |
|
7959 | if (is.element(iframe)) {
|
7960 |
|
7961 | url = parseUrl(iframe.getAttribute('src'));
|
7962 | this.provider = getProviderByUrl(url.toString());
|
7963 |
|
7964 |
|
7965 | this.elements.container = this.media;
|
7966 | this.media = iframe;
|
7967 |
|
7968 |
|
7969 | this.elements.container.className = '';
|
7970 |
|
7971 |
|
7972 | if (url.search.length) {
|
7973 | const truthy = ['1', 'true'];
|
7974 | if (truthy.includes(url.searchParams.get('autoplay'))) {
|
7975 | this.config.autoplay = true;
|
7976 | }
|
7977 | if (truthy.includes(url.searchParams.get('loop'))) {
|
7978 | this.config.loop.active = true;
|
7979 | }
|
7980 |
|
7981 |
|
7982 |
|
7983 | if (this.isYouTube) {
|
7984 | this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));
|
7985 | this.config.youtube.hl = url.searchParams.get('hl');
|
7986 | } else {
|
7987 | this.config.playsinline = true;
|
7988 | }
|
7989 | }
|
7990 | } else {
|
7991 |
|
7992 | this.provider = this.media.getAttribute(this.config.attributes.embed.provider);
|
7993 |
|
7994 |
|
7995 | this.media.removeAttribute(this.config.attributes.embed.provider);
|
7996 | }
|
7997 |
|
7998 |
|
7999 | if (is.empty(this.provider) || !Object.values(providers).includes(this.provider)) {
|
8000 | this.debug.error('Setup failed: Invalid provider');
|
8001 | return;
|
8002 | }
|
8003 |
|
8004 |
|
8005 | this.type = types.video;
|
8006 | break;
|
8007 | case 'video':
|
8008 | case 'audio':
|
8009 | this.type = _type;
|
8010 | this.provider = providers.html5;
|
8011 |
|
8012 |
|
8013 | if (this.media.hasAttribute('crossorigin')) {
|
8014 | this.config.crossorigin = true;
|
8015 | }
|
8016 | if (this.media.hasAttribute('autoplay')) {
|
8017 | this.config.autoplay = true;
|
8018 | }
|
8019 | if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {
|
8020 | this.config.playsinline = true;
|
8021 | }
|
8022 | if (this.media.hasAttribute('muted')) {
|
8023 | this.config.muted = true;
|
8024 | }
|
8025 | if (this.media.hasAttribute('loop')) {
|
8026 | this.config.loop.active = true;
|
8027 | }
|
8028 | break;
|
8029 | default:
|
8030 | this.debug.error('Setup failed: unsupported type');
|
8031 | return;
|
8032 | }
|
8033 |
|
8034 |
|
8035 | this.supported = support.check(this.type, this.provider);
|
8036 |
|
8037 |
|
8038 | if (!this.supported.api) {
|
8039 | this.debug.error('Setup failed: no support');
|
8040 | return;
|
8041 | }
|
8042 | this.eventListeners = [];
|
8043 |
|
8044 |
|
8045 | this.listeners = new Listeners(this);
|
8046 |
|
8047 |
|
8048 | this.storage = new Storage(this);
|
8049 |
|
8050 |
|
8051 | this.media.plyr = this;
|
8052 |
|
8053 |
|
8054 | if (!is.element(this.elements.container)) {
|
8055 | this.elements.container = createElement('div');
|
8056 | wrap(this.media, this.elements.container);
|
8057 | }
|
8058 |
|
8059 |
|
8060 | ui.migrateStyles.call(this);
|
8061 |
|
8062 |
|
8063 | ui.addStyleHook.call(this);
|
8064 |
|
8065 |
|
8066 | media.setup.call(this);
|
8067 |
|
8068 |
|
8069 | if (this.config.debug) {
|
8070 | on.call(this, this.elements.container, this.config.events.join(' '), event => {
|
8071 | this.debug.log(`event: ${event.type}`);
|
8072 | });
|
8073 | }
|
8074 |
|
8075 |
|
8076 | this.fullscreen = new Fullscreen(this);
|
8077 |
|
8078 |
|
8079 |
|
8080 | if (this.isHTML5 || this.isEmbed && !this.supported.ui) {
|
8081 | ui.build.call(this);
|
8082 | }
|
8083 |
|
8084 |
|
8085 | this.listeners.container();
|
8086 |
|
8087 |
|
8088 | this.listeners.global();
|
8089 |
|
8090 |
|
8091 | if (this.config.ads.enabled) {
|
8092 | this.ads = new Ads(this);
|
8093 | }
|
8094 |
|
8095 |
|
8096 | if (this.isHTML5 && this.config.autoplay) {
|
8097 | this.once('canplay', () => silencePromise(this.play()));
|
8098 | }
|
8099 |
|
8100 |
|
8101 | this.lastSeekTime = 0;
|
8102 |
|
8103 |
|
8104 | if (this.config.previewThumbnails.enabled) {
|
8105 | this.previewThumbnails = new PreviewThumbnails(this);
|
8106 | }
|
8107 | }
|
8108 |
|
8109 |
|
8110 |
|
8111 |
|
8112 |
|
8113 | |
8114 |
|
8115 |
|
8116 | get isHTML5() {
|
8117 | return this.provider === providers.html5;
|
8118 | }
|
8119 | get isEmbed() {
|
8120 | return this.isYouTube || this.isVimeo;
|
8121 | }
|
8122 | get isYouTube() {
|
8123 | return this.provider === providers.youtube;
|
8124 | }
|
8125 | get isVimeo() {
|
8126 | return this.provider === providers.vimeo;
|
8127 | }
|
8128 | get isVideo() {
|
8129 | return this.type === types.video;
|
8130 | }
|
8131 | get isAudio() {
|
8132 | return this.type === types.audio;
|
8133 | }
|
8134 | |
8135 |
|
8136 |
|
8137 | get playing() {
|
8138 | return Boolean(this.ready && !this.paused && !this.ended);
|
8139 | }
|
8140 |
|
8141 | |
8142 |
|
8143 |
|
8144 | get paused() {
|
8145 | return Boolean(this.media.paused);
|
8146 | }
|
8147 |
|
8148 | |
8149 |
|
8150 |
|
8151 | get stopped() {
|
8152 | return Boolean(this.paused && this.currentTime === 0);
|
8153 | }
|
8154 |
|
8155 | |
8156 |
|
8157 |
|
8158 | get ended() {
|
8159 | return Boolean(this.media.ended);
|
8160 | }
|
8161 | |
8162 |
|
8163 |
|
8164 |
|
8165 | set currentTime(input) {
|
8166 |
|
8167 | if (!this.duration) {
|
8168 | return;
|
8169 | }
|
8170 |
|
8171 |
|
8172 | const inputIsValid = is.number(input) && input > 0;
|
8173 |
|
8174 |
|
8175 | this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;
|
8176 |
|
8177 |
|
8178 | this.debug.log(`Seeking to ${this.currentTime} seconds`);
|
8179 | }
|
8180 |
|
8181 | |
8182 |
|
8183 |
|
8184 | get currentTime() {
|
8185 | return Number(this.media.currentTime);
|
8186 | }
|
8187 |
|
8188 | |
8189 |
|
8190 |
|
8191 | get buffered() {
|
8192 | const {
|
8193 | buffered
|
8194 | } = this.media;
|
8195 |
|
8196 |
|
8197 | if (is.number(buffered)) {
|
8198 | return buffered;
|
8199 | }
|
8200 |
|
8201 |
|
8202 |
|
8203 |
|
8204 | if (buffered && buffered.length && this.duration > 0) {
|
8205 | return buffered.end(0) / this.duration;
|
8206 | }
|
8207 | return 0;
|
8208 | }
|
8209 |
|
8210 | |
8211 |
|
8212 |
|
8213 | get seeking() {
|
8214 | return Boolean(this.media.seeking);
|
8215 | }
|
8216 |
|
8217 | |
8218 |
|
8219 |
|
8220 | get duration() {
|
8221 |
|
8222 | const fauxDuration = parseFloat(this.config.duration);
|
8223 |
|
8224 | const realDuration = (this.media || {}).duration;
|
8225 | const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;
|
8226 |
|
8227 |
|
8228 | return fauxDuration || duration;
|
8229 | }
|
8230 |
|
8231 | |
8232 |
|
8233 |
|
8234 |
|
8235 | set volume(value) {
|
8236 | let volume = value;
|
8237 | const max = 1;
|
8238 | const min = 0;
|
8239 | if (is.string(volume)) {
|
8240 | volume = Number(volume);
|
8241 | }
|
8242 |
|
8243 |
|
8244 | if (!is.number(volume)) {
|
8245 | volume = this.storage.get('volume');
|
8246 | }
|
8247 |
|
8248 |
|
8249 | if (!is.number(volume)) {
|
8250 | ({
|
8251 | volume
|
8252 | } = this.config);
|
8253 | }
|
8254 |
|
8255 |
|
8256 | if (volume > max) {
|
8257 | volume = max;
|
8258 | }
|
8259 |
|
8260 | if (volume < min) {
|
8261 | volume = min;
|
8262 | }
|
8263 |
|
8264 |
|
8265 | this.config.volume = volume;
|
8266 |
|
8267 |
|
8268 | this.media.volume = volume;
|
8269 |
|
8270 |
|
8271 | if (!is.empty(value) && this.muted && volume > 0) {
|
8272 | this.muted = false;
|
8273 | }
|
8274 | }
|
8275 |
|
8276 | |
8277 |
|
8278 |
|
8279 | get volume() {
|
8280 | return Number(this.media.volume);
|
8281 | }
|
8282 | |
8283 |
|
8284 |
|
8285 |
|
8286 | set muted(mute) {
|
8287 | let toggle = mute;
|
8288 |
|
8289 |
|
8290 | if (!is.boolean(toggle)) {
|
8291 | toggle = this.storage.get('muted');
|
8292 | }
|
8293 |
|
8294 |
|
8295 | if (!is.boolean(toggle)) {
|
8296 | toggle = this.config.muted;
|
8297 | }
|
8298 |
|
8299 |
|
8300 | this.config.muted = toggle;
|
8301 |
|
8302 |
|
8303 | this.media.muted = toggle;
|
8304 | }
|
8305 |
|
8306 | |
8307 |
|
8308 |
|
8309 | get muted() {
|
8310 | return Boolean(this.media.muted);
|
8311 | }
|
8312 |
|
8313 | |
8314 |
|
8315 |
|
8316 | get hasAudio() {
|
8317 |
|
8318 | if (!this.isHTML5) {
|
8319 | return true;
|
8320 | }
|
8321 | if (this.isAudio) {
|
8322 | return true;
|
8323 | }
|
8324 |
|
8325 |
|
8326 | return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length);
|
8327 | }
|
8328 |
|
8329 | |
8330 |
|
8331 |
|
8332 |
|
8333 | set speed(input) {
|
8334 | let speed = null;
|
8335 | if (is.number(input)) {
|
8336 | speed = input;
|
8337 | }
|
8338 | if (!is.number(speed)) {
|
8339 | speed = this.storage.get('speed');
|
8340 | }
|
8341 | if (!is.number(speed)) {
|
8342 | speed = this.config.speed.selected;
|
8343 | }
|
8344 |
|
8345 |
|
8346 | const {
|
8347 | minimumSpeed: min,
|
8348 | maximumSpeed: max
|
8349 | } = this;
|
8350 | speed = clamp(speed, min, max);
|
8351 |
|
8352 |
|
8353 | this.config.speed.selected = speed;
|
8354 |
|
8355 |
|
8356 | setTimeout(() => {
|
8357 | if (this.media) {
|
8358 | this.media.playbackRate = speed;
|
8359 | }
|
8360 | }, 0);
|
8361 | }
|
8362 |
|
8363 | |
8364 |
|
8365 |
|
8366 | get speed() {
|
8367 | return Number(this.media.playbackRate);
|
8368 | }
|
8369 |
|
8370 | |
8371 |
|
8372 |
|
8373 | get minimumSpeed() {
|
8374 | if (this.isYouTube) {
|
8375 |
|
8376 | return Math.min(...this.options.speed);
|
8377 | }
|
8378 | if (this.isVimeo) {
|
8379 |
|
8380 | return 0.5;
|
8381 | }
|
8382 |
|
8383 |
|
8384 | return 0.0625;
|
8385 | }
|
8386 |
|
8387 | |
8388 |
|
8389 |
|
8390 | get maximumSpeed() {
|
8391 | if (this.isYouTube) {
|
8392 |
|
8393 | return Math.max(...this.options.speed);
|
8394 | }
|
8395 | if (this.isVimeo) {
|
8396 |
|
8397 | return 2;
|
8398 | }
|
8399 |
|
8400 |
|
8401 | return 16;
|
8402 | }
|
8403 |
|
8404 | |
8405 |
|
8406 |
|
8407 |
|
8408 |
|
8409 | set quality(input) {
|
8410 | const config = this.config.quality;
|
8411 | const options = this.options.quality;
|
8412 | if (!options.length) {
|
8413 | return;
|
8414 | }
|
8415 | let quality = [!is.empty(input) && Number(input), this.storage.get('quality'), config.selected, config.default].find(is.number);
|
8416 | let updateStorage = true;
|
8417 | if (!options.includes(quality)) {
|
8418 | const value = closest(options, quality);
|
8419 | this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);
|
8420 | quality = value;
|
8421 |
|
8422 |
|
8423 | updateStorage = false;
|
8424 | }
|
8425 |
|
8426 |
|
8427 | config.selected = quality;
|
8428 |
|
8429 |
|
8430 | this.media.quality = quality;
|
8431 |
|
8432 |
|
8433 | if (updateStorage) {
|
8434 | this.storage.set({
|
8435 | quality
|
8436 | });
|
8437 | }
|
8438 | }
|
8439 |
|
8440 | |
8441 |
|
8442 |
|
8443 | get quality() {
|
8444 | return this.media.quality;
|
8445 | }
|
8446 |
|
8447 | |
8448 |
|
8449 |
|
8450 |
|
8451 |
|
8452 | set loop(input) {
|
8453 | const toggle = is.boolean(input) ? input : this.config.loop.active;
|
8454 | this.config.loop.active = toggle;
|
8455 | this.media.loop = toggle;
|
8456 |
|
8457 |
|
8458 | |
8459 |
|
8460 |
|
8461 |
|
8462 |
|
8463 |
|
8464 |
|
8465 |
|
8466 |
|
8467 |
|
8468 |
|
8469 |
|
8470 |
|
8471 |
|
8472 |
|
8473 |
|
8474 |
|
8475 |
|
8476 |
|
8477 |
|
8478 |
|
8479 |
|
8480 |
|
8481 |
|
8482 |
|
8483 |
|
8484 |
|
8485 |
|
8486 |
|
8487 |
|
8488 |
|
8489 |
|
8490 |
|
8491 |
|
8492 |
|
8493 |
|
8494 | }
|
8495 |
|
8496 | |
8497 |
|
8498 |
|
8499 | get loop() {
|
8500 | return Boolean(this.media.loop);
|
8501 | }
|
8502 |
|
8503 | |
8504 |
|
8505 |
|
8506 |
|
8507 | set source(input) {
|
8508 | source.change.call(this, input);
|
8509 | }
|
8510 |
|
8511 | |
8512 |
|
8513 |
|
8514 | get source() {
|
8515 | return this.media.currentSrc;
|
8516 | }
|
8517 |
|
8518 | |
8519 |
|
8520 |
|
8521 | get download() {
|
8522 | const {
|
8523 | download
|
8524 | } = this.config.urls;
|
8525 | return is.url(download) ? download : this.source;
|
8526 | }
|
8527 |
|
8528 | |
8529 |
|
8530 |
|
8531 | set download(input) {
|
8532 | if (!is.url(input)) {
|
8533 | return;
|
8534 | }
|
8535 | this.config.urls.download = input;
|
8536 | controls.setDownloadUrl.call(this);
|
8537 | }
|
8538 |
|
8539 | |
8540 |
|
8541 |
|
8542 |
|
8543 | set poster(input) {
|
8544 | if (!this.isVideo) {
|
8545 | this.debug.warn('Poster can only be set for video');
|
8546 | return;
|
8547 | }
|
8548 | ui.setPoster.call(this, input, false).catch(() => {});
|
8549 | }
|
8550 |
|
8551 | |
8552 |
|
8553 |
|
8554 | get poster() {
|
8555 | if (!this.isVideo) {
|
8556 | return null;
|
8557 | }
|
8558 | return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');
|
8559 | }
|
8560 |
|
8561 | |
8562 |
|
8563 |
|
8564 | get ratio() {
|
8565 | if (!this.isVideo) {
|
8566 | return null;
|
8567 | }
|
8568 | const ratio = reduceAspectRatio(getAspectRatio.call(this));
|
8569 | return is.array(ratio) ? ratio.join(':') : ratio;
|
8570 | }
|
8571 |
|
8572 | |
8573 |
|
8574 |
|
8575 | set ratio(input) {
|
8576 | if (!this.isVideo) {
|
8577 | this.debug.warn('Aspect ratio can only be set for video');
|
8578 | return;
|
8579 | }
|
8580 | if (!is.string(input) || !validateAspectRatio(input)) {
|
8581 | this.debug.error(`Invalid aspect ratio specified (${input})`);
|
8582 | return;
|
8583 | }
|
8584 | this.config.ratio = reduceAspectRatio(input);
|
8585 | setAspectRatio.call(this);
|
8586 | }
|
8587 |
|
8588 | |
8589 |
|
8590 |
|
8591 |
|
8592 | set autoplay(input) {
|
8593 | this.config.autoplay = is.boolean(input) ? input : this.config.autoplay;
|
8594 | }
|
8595 |
|
8596 | |
8597 |
|
8598 |
|
8599 | get autoplay() {
|
8600 | return Boolean(this.config.autoplay);
|
8601 | }
|
8602 |
|
8603 | |
8604 |
|
8605 |
|
8606 |
|
8607 | toggleCaptions(input) {
|
8608 | captions.toggle.call(this, input, false);
|
8609 | }
|
8610 |
|
8611 | |
8612 |
|
8613 |
|
8614 |
|
8615 | set currentTrack(input) {
|
8616 | captions.set.call(this, input, false);
|
8617 | captions.setup.call(this);
|
8618 | }
|
8619 |
|
8620 | |
8621 |
|
8622 |
|
8623 | get currentTrack() {
|
8624 | const {
|
8625 | toggled,
|
8626 | currentTrack
|
8627 | } = this.captions;
|
8628 | return toggled ? currentTrack : -1;
|
8629 | }
|
8630 |
|
8631 | |
8632 |
|
8633 |
|
8634 |
|
8635 |
|
8636 | set language(input) {
|
8637 | captions.setLanguage.call(this, input, false);
|
8638 | }
|
8639 |
|
8640 | |
8641 |
|
8642 |
|
8643 | get language() {
|
8644 | return (captions.getCurrentTrack.call(this) || {}).language;
|
8645 | }
|
8646 |
|
8647 | |
8648 |
|
8649 |
|
8650 |
|
8651 |
|
8652 | set pip(input) {
|
8653 |
|
8654 | if (!support.pip) {
|
8655 | return;
|
8656 | }
|
8657 |
|
8658 |
|
8659 | const toggle = is.boolean(input) ? input : !this.pip;
|
8660 |
|
8661 |
|
8662 |
|
8663 | if (is.function(this.media.webkitSetPresentationMode)) {
|
8664 | this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);
|
8665 | }
|
8666 |
|
8667 |
|
8668 | if (is.function(this.media.requestPictureInPicture)) {
|
8669 | if (!this.pip && toggle) {
|
8670 | this.media.requestPictureInPicture();
|
8671 | } else if (this.pip && !toggle) {
|
8672 | document.exitPictureInPicture();
|
8673 | }
|
8674 | }
|
8675 | }
|
8676 |
|
8677 | |
8678 |
|
8679 |
|
8680 | get pip() {
|
8681 | if (!support.pip) {
|
8682 | return null;
|
8683 | }
|
8684 |
|
8685 |
|
8686 | if (!is.empty(this.media.webkitPresentationMode)) {
|
8687 | return this.media.webkitPresentationMode === pip.active;
|
8688 | }
|
8689 |
|
8690 |
|
8691 | return this.media === document.pictureInPictureElement;
|
8692 | }
|
8693 |
|
8694 | |
8695 |
|
8696 |
|
8697 | setPreviewThumbnails(thumbnailSource) {
|
8698 | if (this.previewThumbnails && this.previewThumbnails.loaded) {
|
8699 | this.previewThumbnails.destroy();
|
8700 | this.previewThumbnails = null;
|
8701 | }
|
8702 | Object.assign(this.config.previewThumbnails, thumbnailSource);
|
8703 |
|
8704 |
|
8705 | if (this.config.previewThumbnails.enabled) {
|
8706 | this.previewThumbnails = new PreviewThumbnails(this);
|
8707 | }
|
8708 | }
|
8709 | |
8710 |
|
8711 |
|
8712 |
|
8713 |
|
8714 | static supported(type, provider) {
|
8715 | return support.check(type, provider);
|
8716 | }
|
8717 |
|
8718 | |
8719 |
|
8720 |
|
8721 |
|
8722 |
|
8723 | static loadSprite(url, id) {
|
8724 | return loadSprite(url, id);
|
8725 | }
|
8726 |
|
8727 | |
8728 |
|
8729 |
|
8730 |
|
8731 |
|
8732 | static setup(selector, options = {}) {
|
8733 | let targets = null;
|
8734 | if (is.string(selector)) {
|
8735 | targets = Array.from(document.querySelectorAll(selector));
|
8736 | } else if (is.nodeList(selector)) {
|
8737 | targets = Array.from(selector);
|
8738 | } else if (is.array(selector)) {
|
8739 | targets = selector.filter(is.element);
|
8740 | }
|
8741 | if (is.empty(targets)) {
|
8742 | return null;
|
8743 | }
|
8744 | return targets.map(t => new Plyr(t, options));
|
8745 | }
|
8746 | }
|
8747 | Plyr.defaults = cloneDeep(defaults);
|
8748 |
|
8749 | export { Plyr as default };
|
8750 |
|