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