UNPKG

@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
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);