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