@exadel/esl
Version:
Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components
126 lines (125 loc) • 4.86 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { ESLEventUtils } from '../../esl-event-listener/core/api';
import { isSafeContains } from '../../esl-utils/dom/traversing';
import { isVisible } from '../../esl-utils/dom/visible';
import { listen } from '../../esl-utils/decorators';
import { ESLMediaHookEvent } from './esl-media.events';
/**
* Manager for {@link ESLMedia}
* Checks whether media should play inside ESLToggleable container,
* stores all active instances and instances marked with `autoplay` attribute
* Restrict that only one media from the group can be played
*
* @author Anastasia Lesun
*/
export class ESLMediaManager {
/** Active instances */
get active() {
return Array.from(this.instances).filter((player) => player.active);
}
/** Instances with autoplay marker */
get autoplayable() {
return Array.from(this.instances).filter((player) => player.autoplay);
}
constructor() {
/** All managed instances */
this.instances = new Set();
ESLEventUtils.subscribe(this);
}
/** Hook for {@link ESLMedia} initialization */
_onInit(media) {
this.instances.add(media);
}
/** Hook for {@link ESLMedia} destroy */
_onDestroy(media) {
this.instances.delete(media);
}
/** Hook for {@link ESLMedia} which is started to play */
_onAfterPlay(media) {
this.active.forEach((player) => {
if (player === media)
return;
if (!media.group || player.group !== media.group)
return;
const event = new ESLMediaHookEvent(player.MANAGED_PAUSE_EVENT, {
initiator: 'system',
relatedMedia: media
});
if (player.dispatchEvent(event))
player.pause(true);
});
}
/**
* Processes {@link ESLToggleable} show event and resumes all media inside.
* @see {@link ESLMediaManager#releaseAll}
*/
_onContainerShow(e) {
this.releaseAll(e.target);
}
/**
* Processes {@link ESLToggleable} hide event and systemically suspend all media instances inside.
* @see {@link ESLMediaManager#suspendAll}
*/
_onContainerHide(e) {
this.suspendAll(e.target);
}
/**
* Starts all system-stopped media with autoplay marker
* @param scope - the scope to search for media
* @param system - whether to start only system-stopped media
*/
releaseAll(scope = document.body, system = true) {
this.autoplayable.forEach(($media) => {
if (system && $media.isUserInitiated)
return;
if (!$media.autoplay)
return;
if (!isSafeContains(scope, $media))
return;
if (!isVisible($media, { visibility: true, viewport: $media.playInViewport }))
return;
$media.play(false, true);
});
}
/**
* Pauses all active media that was not started manually
* @param scope - the scope to search for media
* @param system - whether to pause only system-active media
*/
suspendAll(scope = document.body, system = true) {
// Pause all instances (to notify an inner player about the pause)
// Note: Chrome may try to play automatically paused video even if it in paused state
this.instances.forEach(($media) => {
if (system && $media.isUserInitiated)
return;
if (!isSafeContains(scope, $media))
return;
$media.pause(true);
});
}
/** Processes request to play/pause media */
_onRequest(e) {
switch (e.detail.action) {
case 'release':
this.releaseAll(e.detail.scope, !e.detail.force);
break;
case 'suspend':
this.suspendAll(e.detail.scope, !e.detail.force);
break;
}
}
}
__decorate([
listen({ event: 'esl:show', target: window })
], ESLMediaManager.prototype, "_onContainerShow", null);
__decorate([
listen({ event: 'esl:hide', target: window })
], ESLMediaManager.prototype, "_onContainerHide", null);
__decorate([
listen({ event: 'esl:media:managedaction', target: window })
], ESLMediaManager.prototype, "_onRequest", null);