UNPKG

@aws-amplify/analytics

Version:

Analytics category of aws-amplify

197 lines (172 loc) 4.75 kB
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import { RequestParams } from './DataType'; enum HTML5_MEDIA_EVENT { 'PLAY' = 'play', 'PAUSE' = 'pause', 'ENDED' = 'Ended', } enum MEDIA_TYPE { 'IFRAME' = 'IFRAME', 'VIDEO' = 'VIDEO', 'AUDIO' = 'AUDIO', } enum EVENT_TYPE { 'PLAY' = 'Play', 'ENDED' = 'Ended', 'PAUSE' = 'Pause', 'TIME_WATCHED' = 'TimeWatched', } export class MediaAutoTrack { private _mediaElement; private _provider; private _params; private _started; private _iframePlayer; private eventActionMapping = { [EVENT_TYPE.ENDED]: this.endedEventAction.bind(this), [EVENT_TYPE.PLAY]: this.playEventAction.bind(this), [EVENT_TYPE.PAUSE]: this.pauseEventAction.bind(this), }; private _youTubeIframeLoader; constructor(params: RequestParams, provider) { const { eventData } = params; this._params = params; this._mediaElement = document.getElementById( eventData.properties['domElementId'] ); this._started = false; this._provider = provider; const mediaTrackFunMapping = { IFRAME: this._iframeMediaTracker, VIDEO: this._html5MediaTracker, AUDIO: this._html5MediaTracker, }; mediaTrackFunMapping[this._mediaElement.tagName].bind(this)(); this._initYoutubeFrame(); } private _initYoutubeFrame() { this._youTubeIframeLoader = { src: 'https://www.youtube.com/iframe_api', loading: false, loaded: false, listeners: [], load(callback) { const _this = this; this.listeners.push(callback); if (this.loaded) { setTimeout(function() { _this.done(); }); return; } if (this.loading) { return; } this.loading = true; window['onYouTubeIframeAPIReady'] = function() { _this.loaded = true; _this.done(); }; const script = document.createElement('script'); script.type = 'text/javascript'; script.src = this.src; document.body.appendChild(script); }, done() { delete window['onYouTubeIframeAPIReady']; while (this.listeners.length) { this.listeners.pop()(window['YT']); } }, }; } private _iframeMediaTracker(): void { const that = this; setInterval(function() { if (that._started) { that.recordEvent(MEDIA_TYPE.IFRAME, EVENT_TYPE.TIME_WATCHED); } }, 3 * 1000); this._youTubeIframeLoader.load(function(YT) { that._iframePlayer = new YT.Player(that._mediaElement.id, { events: { onStateChange: that._onPlayerStateChange.bind(that) }, }); }); } private _onPlayerStateChange(event): void { const iframeEventMapping = { 0: EVENT_TYPE.ENDED, 1: EVENT_TYPE.PLAY, 2: EVENT_TYPE.PAUSE, }; const eventType = iframeEventMapping[event.data]; if (eventType) { this.eventActionMapping[eventType](MEDIA_TYPE.IFRAME); } } private _html5MediaTracker(): void { const that = this; setInterval(function() { if (that._started) { that.recordEvent(MEDIA_TYPE.VIDEO, EVENT_TYPE.TIME_WATCHED); } }, 3 * 1000); this._mediaElement.addEventListener( HTML5_MEDIA_EVENT.PLAY, () => { that.eventActionMapping[EVENT_TYPE.PLAY](MEDIA_TYPE.VIDEO); }, false ); this._mediaElement.addEventListener( HTML5_MEDIA_EVENT.PAUSE, () => { that.eventActionMapping[EVENT_TYPE.PAUSE](MEDIA_TYPE.VIDEO); }, false ); this._mediaElement.addEventListener( HTML5_MEDIA_EVENT.ENDED, () => { that.eventActionMapping[EVENT_TYPE.ENDED](MEDIA_TYPE.VIDEO); }, false ); } private playEventAction(mediaType) { this._started = true; this.recordEvent(mediaType, EVENT_TYPE.PLAY); } private pauseEventAction(mediaType) { this._started = false; this.recordEvent(mediaType, EVENT_TYPE.PAUSE); } private endedEventAction(mediaType) { this._started = false; this.recordEvent(mediaType, EVENT_TYPE.ENDED); } private recordEvent(mediaType: string, eventType: string): void { const newParams = Object.assign({}, this._params); const { eventData } = newParams; eventData.eventType = eventType; let currentPlayTime: string; if (mediaType === MEDIA_TYPE.VIDEO) { currentPlayTime = this._mediaElement.currentTime; eventData.properties.duration = this._mediaElement.duration; } else { currentPlayTime = this._financial(this._iframePlayer.getCurrentTime()); eventData.properties.duration = this._financial( this._iframePlayer.getDuration() ); } const percentage = parseFloat(currentPlayTime) / parseFloat(eventData.properties.duration); eventData.properties.eventValue = Number(percentage.toFixed(4)); delete eventData.properties.domElementId; this._provider.putToBuffer(newParams); } private _financial(x) { return Number.parseFloat(x).toFixed(4); } }