UNPKG

@nent/core

Version:

Functional elements to add routing, data-binding, dynamic HTML, declarative actions, audio, video, and so much more. Supercharge static HTML files into web apps without script or builds.

108 lines (107 loc) 4.45 kB
/*! * NENT 2022 */ import { actionBus } from '../../../services/actions'; import { activateActionActivators, sendActions, } from '../../../services/actions/elements'; import { ActionActivationStrategy, } from '../../../services/actions/interfaces'; import { debugIf, error } from '../../../services/common/logging'; import { ANALYTICS_COMMANDS, ANALYTICS_TOPIC, } from '../../n-app-analytics/services/interfaces'; import { captureElementChildTimedNodes, resolveElementChildTimedNodesByTime, restoreElementChildTimedNodes, } from './elements'; import { TIMER_EVENTS, } from './interfaces'; /* It subscribes to the timer's `OnInterval` and `OnEnd` events, and when those events are emitted, it activates any `n-action-activator` elements that are configured to activate at that time, and it also sends any `n-presentation-action` elements that are configured to send at that time */ export class PresentationService { /** * > This function creates a new instance of the Presentation class * @param {HTMLElement} el - HTMLElement - the element that will be the root of the presentation * @param {ITimer} timeEmitter - ITimer * @param {boolean} [elements=false] - boolean = false * @param {string | null} [analyticsEvent=null] - string | null = null * @param {(() => void) | null} [onEnd=null] - (() => void) | null = null, * @param {boolean} [debug=false] - boolean = false, */ constructor(el, timeEmitter, elements = false, analyticsEvent = null, onEnd = null, debug = false) { this.el = el; this.timeEmitter = timeEmitter; this.elements = elements; this.analyticsEvent = analyticsEvent; this.onEnd = onEnd; this.debug = debug; this.timedNodes = []; this.activatedActions = []; if (this.elements) { this.timedNodes = captureElementChildTimedNodes(this.el, this.timeEmitter.durationSeconds); debugIf(this.debug, `presentation: found ${this.timedNodes.length} timed-child elements`); } debugIf(this.debug, `presentation: service created`); } get actionActivators() { return Array.from(this.el.querySelectorAll('n-action-activator')); } get actions() { return Array.from(this.el.querySelectorAll('n-presentation-action')).map(a => a); } async handleInterval(time) { if (this.elements) { resolveElementChildTimedNodesByTime(this.el, this.timedNodes, time.elapsedSeconds, time.percentage); } if (this.analyticsEvent) { const data = { event: this.analyticsEvent, time, }; actionBus.emit(ANALYTICS_TOPIC, { topic: ANALYTICS_TOPIC, command: ANALYTICS_COMMANDS.SendViewTime, data, }); } await activateActionActivators(this.actionActivators, ActionActivationStrategy.AtTime, activator => { if (this.activatedActions.includes(activator)) return false; if (activator.time && time.elapsedSeconds >= activator.time) { this.activatedActions.push(activator); return true; } return false; }); await sendActions(this.actions, action => { return action.time && time.elapsedSeconds >= action.time; }); } async handleEnded(time) { var _a; if (this.elements) { resolveElementChildTimedNodesByTime(this.el, this.timedNodes, time.elapsedSeconds, time.percentage); } await activateActionActivators(this.actionActivators, ActionActivationStrategy.AtTimeEnd); await sendActions(this.actions, action => { return action.time == 'end'; }); (_a = this.onEnd) === null || _a === void 0 ? void 0 : _a.call(this); } /** * > The function subscribes to the `timeEmitter` and listens for the `OnInterval` and `OnEnd` events */ subscribe() { this.intervalSubscription = this.timeEmitter.on(TIMER_EVENTS.OnInterval, (time) => { this.handleInterval(time).catch(e => error(e)); }); this.endSubscription = this.timeEmitter.on(TIMER_EVENTS.OnEnd, (time) => { debugIf(this.debug, `presentation: ended`); this.handleEnded(time).catch(e => error(e)); }); } /** * It unsubscribes from the interval and end subscriptions. */ unsubscribe() { var _a, _b; if (this.elements) { restoreElementChildTimedNodes(this.el, this.timedNodes); } (_a = this.intervalSubscription) === null || _a === void 0 ? void 0 : _a.call(this); (_b = this.endSubscription) === null || _b === void 0 ? void 0 : _b.call(this); } }