UNPKG

fluid-player

Version:

Fluid Player is a free HTML5 video player

1,208 lines (964 loc) 65.7 kB
'use strict'; export default function (playerInstance, options) { const VPAID_VERSION = '2.0'; playerInstance.renderLinearAd = (adListId, backupTheVideoTime) => { playerInstance.toggleLoader(false); //get the proper ad playerInstance.vastOptions = playerInstance.adPool[adListId]; if (backupTheVideoTime) { playerInstance.backupMainVideoContentTime(adListId); } const playVideoPlayer = adListId => { playerInstance.switchPlayerToVpaidMode = adListId => { playerInstance.debugMessage('starting function switchPlayerToVpaidMode'); const vpaidIframe = playerInstance.videoPlayerId + "_" + adListId + "_fluid_vpaid_iframe"; const creativeData = {}; creativeData.AdParameters = playerInstance.adPool[adListId].adParameters; const slotElement = document.createElement('div'); slotElement.id = playerInstance.videoPlayerId + "_fluid_vpaid_slot"; slotElement.className = 'fluid_vpaid_slot'; slotElement.setAttribute('adListId', adListId); playerInstance.domRef.player.parentNode.insertBefore(slotElement, vpaidIframe.nextSibling); const environmentVars = { slot: slotElement, videoSlot: playerInstance.domRef.player, videoSlotCanAutoPlay: true }; // calls this functions after ad unit is loaded in iframe const ver = playerInstance.vpaidAdUnit.handshakeVersion(VPAID_VERSION); const compare = playerInstance.compareVersion(VPAID_VERSION, ver); if (compare === 1) { //VPAID version of ad is lower than we need playerInstance.adList[adListId].error = true; playerInstance.playMainVideoWhenVpaidFails(403); return false; } if (playerInstance.vastOptions.skipoffset !== false) { playerInstance.addSkipButton(); } playerInstance.domRef.player.loop = false; playerInstance.domRef.player.removeAttribute('controls'); //Remove the default Controls playerInstance.vpaidCallbackListenersAttach(); const mode = (playerInstance.fullscreenMode ? 'fullscreen' : 'normal'); const adWidth = playerInstance.domRef.player.offsetWidth; const adHeight = playerInstance.domRef.player.offsetHeight; playerInstance.vpaidAdUnit.initAd(adWidth, adHeight, mode, 3000, creativeData, environmentVars); const progressbarContainer = playerInstance.domRef.player.parentNode.getElementsByClassName('fluid_controls_currentprogress'); for (let i = 0; i < progressbarContainer.length; i++) { progressbarContainer[i].style.backgroundColor = playerInstance.displayOptions.layoutControls.adProgressColor; } playerInstance.toggleLoader(false); playerInstance.adList[adListId].played = true; playerInstance.adFinished = false; }; playerInstance.switchPlayerToVastMode = () => { // Get the actual duration from the video file if it is not present in the VAST XML if (!playerInstance.vastOptions.duration) { playerInstance.vastOptions.duration = selectedMediaFile.delivery === 'streaming' ? Infinity : playerInstance.domRef.player.duration; } if (playerInstance.displayOptions.layoutControls.showCardBoardView) { if (!playerInstance.adList[adListId].landingPage) { playerInstance.addCTAButton(playerInstance.adPool[adListId].clickthroughUrl); } else { playerInstance.addCTAButton(playerInstance.adList[adListId].landingPage); } } else { const addClickthroughLayer = (typeof playerInstance.adList[adListId].adClickable != "undefined") ? playerInstance.adList[adListId].adClickable : playerInstance.displayOptions.vastOptions.adClickable; if (addClickthroughLayer) { playerInstance.addClickthroughLayer(playerInstance.videoPlayerId); } playerInstance.addCTAButton(playerInstance.adList[adListId].landingPage); } if (playerInstance.vastOptions.skipoffset !== false) { playerInstance.addSkipButton(); } playerInstance.domRef.player.loop = false; playerInstance.addAdCountdown(); playerInstance.domRef.player.removeAttribute('controls'); //Remove the default Controls playerInstance.vastLogoBehaviour(true); const progressbarContainer = playerInstance.domRef.player.parentNode.getElementsByClassName('fluid_controls_currentprogress'); for (let i = 0; i < progressbarContainer.length; i++) { progressbarContainer[i].style.backgroundColor = playerInstance.displayOptions.layoutControls.adProgressColor; } if (playerInstance.displayOptions.vastOptions.adText || playerInstance.adList[adListId].adText) { const adTextToShow = (playerInstance.adList[adListId].adText !== null) ? playerInstance.adList[adListId].adText : playerInstance.displayOptions.vastOptions.adText; playerInstance.addAdPlayingText(adTextToShow); } playerInstance.positionTextElements(playerInstance.adList[adListId]); playerInstance.toggleLoader(false); playerInstance.adList[adListId].played = true; playerInstance.adFinished = false; playerInstance.domRef.player.play(); //Announce the impressions playerInstance.trackSingleEvent('impression'); playerInstance.domRef.player.removeEventListener('loadedmetadata', playerInstance.switchPlayerToVastMode); // if in vr mode then do not show if (playerInstance.vrMode) { const adCountDownTimerText = document.getElementById('ad_countdown' + playerInstance.videoPlayerId); const ctaButton = document.getElementById(playerInstance.videoPlayerId + '_fluid_cta'); const addAdPlayingTextOverlay = document.getElementById(playerInstance.videoPlayerId + '_fluid_ad_playing'); const skipBtn = document.getElementById('skip_button_' + playerInstance.videoPlayerId); if (adCountDownTimerText) { adCountDownTimerText.style.display = 'none'; } if (ctaButton) { ctaButton.style.display = 'none'; } if (addAdPlayingTextOverlay) { addAdPlayingTextOverlay.style.display = 'none'; } if (skipBtn) { skipBtn.style.display = 'none'; } } }; playerInstance.domRef.player.pause(); // Remove the streaming objects to prevent errors on the VAST content playerInstance.detachStreamers(); // Try to load multiple const selectedMediaFile = playerInstance.getSupportedMediaFileObject(playerInstance.vastOptions.mediaFileList); // if player in cardboard mode then, linear ads media type should be a '360' video if (playerInstance.displayOptions.layoutControls.showCardBoardView && playerInstance.adList[adListId].mediaType !== '360') { playerInstance.adList[adListId].error = true; playerInstance.playMainVideoWhenVastFails(403); return false; } const isVpaid = playerInstance.vastOptions.vpaid; if (!isVpaid && selectedMediaFile.isUnsuportedHls) { import(/* webpackChunkName: "hlsjs" */ 'hls.js').then((it) => { window.Hls = it.default; const hls = new Hls({ debug: typeof FP_DEBUG !== 'undefined' && FP_DEBUG === true, p2pConfig: { logLevel: false, }, enableWebVTT: false, enableCEA708Captions: false, }); hls.attachMedia(playerInstance.domRef.player); hls.loadSource(selectedMediaFile.src); playerInstance.isCurrentlyPlayingAd = true; playerInstance.hlsPlayer = hls; playerInstance.domRef.player.addEventListener('loadedmetadata', playerInstance.switchPlayerToVastMode); playerInstance.domRef.player.addEventListener('ended', () => { hls.detachMedia(); hls.destroy(); playerInstance.hlsPlayer = false; playerInstance.onVastAdEnded(); }); playerInstance.domRef.player.play(); }); } else if (!isVpaid) { if (selectedMediaFile.src === false) { // Couldn’t find MediaFile that is supported by this video player, based on the attributes of the MediaFile element. playerInstance.adList[adListId].error = true; playerInstance.playMainVideoWhenVastFails(403); return false; } playerInstance.domRef.player.addEventListener('loadedmetadata', playerInstance.switchPlayerToVastMode); playerInstance.domRef.player.src = selectedMediaFile.src; playerInstance.isCurrentlyPlayingAd = true; if (playerInstance.displayOptions.vastOptions.showProgressbarMarkers) { playerInstance.hideAdMarkers(); } playerInstance.domRef.player.load(); //Handle the ending of the Pre-Roll ad playerInstance.domRef.player.addEventListener('ended', playerInstance.onVastAdEnded); } else { playerInstance.loadVpaid(adListId, selectedMediaFile.src); if (playerInstance.displayOptions.vastOptions.showProgressbarMarkers) { playerInstance.hideAdMarkers(); } } }; /** * Sends requests to the tracking URIs */ const videoPlayerTimeUpdate = () => { if (playerInstance.adFinished) { playerInstance.domRef.player.removeEventListener('timeupdate', videoPlayerTimeUpdate); return; } const currentTime = Math.floor(playerInstance.domRef.player.currentTime); if (playerInstance.vastOptions.duration !== 0) { playerInstance.scheduleTrackingEvent(currentTime, playerInstance.vastOptions.duration); } if (currentTime >= (playerInstance.vastOptions.duration - 1) && playerInstance.vastOptions.duration !== 0) { playerInstance.domRef.player.removeEventListener('timeupdate', videoPlayerTimeUpdate); playerInstance.adFinished = true; } }; playVideoPlayer(adListId); playerInstance.domRef.player.addEventListener('timeupdate', videoPlayerTimeUpdate); }; playerInstance.playRoll = (adListId) => { // register all the ad pods for (let i = 0; i < adListId.length; i++) { if (!playerInstance.adPool.hasOwnProperty(adListId[i])) { playerInstance.announceLocalError(101); return; } playerInstance.temporaryAdPods.push(playerInstance.adList[adListId[i]]); } if (playerInstance.vastOptions !== null && playerInstance.vastOptions.adType.toLowerCase() === 'linear') { return; } const adListIdToPlay = playerInstance.getNextAdPod(); if (adListIdToPlay !== null) { playerInstance.renderLinearAd(adListIdToPlay, true); } }; playerInstance.backupMainVideoContentTime = (adListId) => { const roll = playerInstance.adList[adListId].roll; //spec configs by roll switch (roll) { case 'midRoll': playerInstance.domRef.player.mainVideoCurrentTime = playerInstance.domRef.player.currentTime - 1; break; case 'postRoll': playerInstance.domRef.player.mainVideoCurrentTime = playerInstance.mainVideoDuration; playerInstance.autoplayAfterAd = false; playerInstance.domRef.player.currentTime = playerInstance.mainVideoDuration; break; case 'preRoll': if (playerInstance.domRef.player.currentTime > 0) { playerInstance.domRef.player.mainVideoCurrentTime = playerInstance.domRef.player.currentTime - 1; } break; } }; playerInstance.getSupportedMediaFileObject = (mediaFiles) => { let selectedMediaFile = null; let adSupportedType = false; if (mediaFiles.length) { for (let i = 0; i < mediaFiles.length; i++) { if (mediaFiles[i].apiFramework !== 'VPAID') { const supportLevel = playerInstance.getMediaFileTypeSupportLevel(mediaFiles[i]['type']); if (supportLevel === 'maybe' || supportLevel === 'probably') { selectedMediaFile = mediaFiles[i]; adSupportedType = true; } //one of the best(s) option, no need to seek more if (supportLevel === 'probably') { break; } if ( supportLevel === 'no' && mediaFiles[i].delivery === 'streaming' && (mediaFiles[i].type === 'application/vnd.apple.mpegurl' || mediaFiles[i].type === 'application/x-mpegURL') ) { selectedMediaFile = mediaFiles[i]; selectedMediaFile.isUnsuportedHls = true; adSupportedType = true; } } else { selectedMediaFile = mediaFiles[i]; adSupportedType = true; break; } } } if (adSupportedType === false) { return false; } return selectedMediaFile; }; /** * Reports how likely it is that the current browser will be able to play media of a given MIME type. * @return string|null "probably", "maybe", "no" or null */ playerInstance.getMediaFileTypeSupportLevel = (mediaType) => { if (null === mediaType) { return null; } const tmpVideo = document.createElement('video'); let response = tmpVideo.canPlayType(mediaType); return !response ? "no" : response; }; playerInstance.scheduleTrackingEvent = (currentTime, duration) => { if (currentTime === 0) { playerInstance.trackSingleEvent('start'); } if ((typeof playerInstance.vastOptions.tracking['progress'] !== 'undefined') && (playerInstance.vastOptions.tracking['progress'].length) && (typeof playerInstance.vastOptions.tracking['progress'][currentTime] !== 'undefined')) { playerInstance.trackSingleEvent('progress', currentTime); } if (currentTime === (Math.floor(duration / 4))) { playerInstance.trackSingleEvent('firstQuartile'); } if (currentTime === (Math.floor(duration / 2))) { playerInstance.trackSingleEvent('midpoint'); } if (currentTime === (Math.floor(duration * 3 / 4))) { playerInstance.trackSingleEvent('thirdQuartile'); } if (currentTime >= (duration - 1)) { playerInstance.trackSingleEvent('complete'); } }; // ADS playerInstance.trackSingleEvent = (eventType, eventSubType) => { if (typeof playerInstance.vastOptions === 'undefined' || playerInstance.vastOptions === null) { return; } let trackingUris = []; trackingUris.length = 0; switch (eventType) { case 'start': case 'firstQuartile': case 'midpoint': case 'thirdQuartile': case 'complete': if (playerInstance.vastOptions.stopTracking[eventType] === false) { if (playerInstance.vastOptions.tracking[eventType] !== null) { trackingUris = playerInstance.vastOptions.tracking[eventType]; } playerInstance.vastOptions.stopTracking[eventType] = true; } break; case 'progress': playerInstance.vastOptions.tracking['progress'][eventSubType].elements.forEach(function (currentValue, index) { if ( (playerInstance.vastOptions.tracking['progress'][eventSubType].stopTracking === false) && (playerInstance.vastOptions.tracking['progress'][eventSubType].elements.length) ) { trackingUris = playerInstance.vastOptions.tracking['progress'][eventSubType].elements; } playerInstance.vastOptions.tracking['progress'][eventSubType].stopTracking = true; }); break; case 'impression': if ( (typeof playerInstance.vastOptions.impression !== 'undefined') && (playerInstance.vastOptions.impression !== null) && (typeof playerInstance.vastOptions.impression.length !== 'undefined') ) { trackingUris = playerInstance.vastOptions.impression; } break; default: break; } playerInstance.callUris(trackingUris); }; // ADS playerInstance.completeNonLinearStatic = (adListId) => { playerInstance.closeNonLinear(adListId); if (playerInstance.adFinished === false) { playerInstance.adFinished = true; playerInstance.trackSingleEvent('complete'); } clearInterval(playerInstance.nonLinearTracking); }; // ADS /** * Show up a nonLinear static creative */ playerInstance.createNonLinearStatic = (adListId) => { if (!playerInstance.adPool.hasOwnProperty(adListId) || playerInstance.adPool[adListId].error === true) { playerInstance.announceLocalError(101); return; } //get the proper ad playerInstance.vastOptions = playerInstance.adPool[adListId]; playerInstance.createBoard(adListId); if (playerInstance.adList[adListId].error === true) { return; } playerInstance.adFinished = false; let duration; if (!playerInstance.vastOptions.vpaid) { playerInstance.trackSingleEvent('start'); duration = (playerInstance.adList[adListId].nonLinearDuration) ? playerInstance.adList[adListId].nonLinearDuration : playerInstance.vastOptions.duration; playerInstance.nonLinearTracking = setInterval(function () { if (playerInstance.adFinished === true) { return; } const currentTime = Math.floor(playerInstance.domRef.player.currentTime); playerInstance.scheduleTrackingEvent(currentTime, duration); if (currentTime >= (duration - 1)) { playerInstance.adFinished = true; } }, 400); } const time = parseInt(playerInstance.getCurrentTime()) + parseInt(duration); playerInstance.scheduleTask({time: time, closeStaticAd: adListId}); }; // ADS playerInstance.createVpaidNonLinearBoard = (adListId) => { // create iframe // pass the js const vastSettings = playerInstance.adPool[adListId]; playerInstance.loadVpaidNonlinearAssets = function (adListId) { playerInstance.debugMessage('starting function switchPlayerToVpaidMode'); const vAlign = (playerInstance.adList[adListId].vAlign) ? playerInstance.adList[adListId].vAlign : playerInstance.nonLinearVerticalAlign; const showCloseButton = (playerInstance.adList[adListId].vpaidNonLinearCloseButton) ? playerInstance.adList[adListId].vpaidNonLinearCloseButton : playerInstance.vpaidNonLinearCloseButton; const vpaidIframe = playerInstance.videoPlayerId + "_" + adListId + "_fluid_vpaid_iframe"; const creativeData = {}; creativeData.AdParameters = playerInstance.adPool[adListId].adParameters; const slotWrapper = document.createElement('div'); slotWrapper.id = 'fluid_vpaidNonLinear_' + adListId; slotWrapper.className = 'fluid_vpaidNonLinear_' + vAlign; slotWrapper.className += ' fluid_vpaidNonLinear_ad'; slotWrapper.setAttribute('adListId', adListId); // Default values in case nothing defined in VAST data or ad settings let adWidth = Math.min(468, playerInstance.domRef.player.offsetWidth); let adHeight = Math.min(60, Math.floor(playerInstance.domRef.player.offsetHeight / 4)); if (typeof playerInstance.adList[adListId].size !== 'undefined') { const dimensions = playerInstance.adList[adListId].size.split('x'); adWidth = dimensions[0]; adHeight = dimensions[1]; } else if (vastSettings.dimension.width && vastSettings.dimension.height) { adWidth = vastSettings.dimension.width; adHeight = vastSettings.dimension.height; } slotWrapper.style.width = '100%'; slotWrapper.style.height = adHeight + 'px'; let slotFrame; if (showCloseButton) { const slotFrame = document.createElement('div'); slotFrame.className = 'fluid_vpaidNonLinear_frame'; slotFrame.style.width = adWidth + 'px'; slotFrame.style.height = adHeight + 'px'; slotWrapper.appendChild(slotFrame); const closeBtn = document.createElement('div'); closeBtn.id = 'close_button_' + playerInstance.videoPlayerId; closeBtn.className = 'close_button'; closeBtn.innerHTML = ''; closeBtn.title = playerInstance.displayOptions.layoutControls.closeButtonCaption; const tempadListId = adListId; closeBtn.onclick = function (event) { playerInstance.hardStopVpaidAd(''); if (typeof event.stopImmediatePropagation !== 'undefined') { event.stopImmediatePropagation(); } playerInstance.adFinished = true; //if any other onPauseRoll then render it if (playerInstance.adList[tempadListId].roll === 'onPauseRoll' && playerInstance.onPauseRollAdPods[0]) { const getNextOnPauseRollAd = playerInstance.onPauseRollAdPods[0]; playerInstance.createBoard(getNextOnPauseRollAd); playerInstance.currentOnPauseRollAd = playerInstance.onPauseRollAdPods[0]; delete playerInstance.onPauseRollAdPods[0]; } return false; }; slotFrame.appendChild(closeBtn); } const slotIframe = document.createElement('iframe'); slotIframe.id = playerInstance.videoPlayerId + "non_linear_vapid_slot_iframe"; slotIframe.className = 'fluid_vpaid_nonlinear_slot_iframe'; slotIframe.setAttribute('width', adWidth + 'px'); slotIframe.setAttribute('height', adHeight + 'px'); slotIframe.setAttribute('sandbox', 'allow-forms allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts'); slotIframe.setAttribute('frameborder', '0'); slotIframe.setAttribute('scrolling', 'no'); slotIframe.setAttribute('marginwidth', '0'); slotIframe.setAttribute('marginheight', '0'); slotWrapper.appendChild(slotIframe); playerInstance.domRef.player.parentNode.insertBefore(slotWrapper, vpaidIframe.nextSibling); const slotElement = slotIframe.contentWindow.document.createElement('div'); slotIframe.contentWindow.document.body.appendChild(slotElement); playerInstance.vastOptions.slotIframe = slotIframe; playerInstance.vastOptions.slotFrame = slotFrame; const environmentVars = { slot: slotElement, videoSlot: playerInstance.domRef.player, videoSlotCanAutoPlay: true }; playerInstance.debugMessage(playerInstance.adList[adListId]); // calls this functions after ad unit is loaded in iframe const ver = playerInstance.vpaidAdUnit.handshakeVersion(VPAID_VERSION); const compare = playerInstance.compareVersion(VPAID_VERSION, ver); if (compare === 1) { //VPAID version of ad is lower than we need playerInstance.adList[adListId].error = true; playerInstance.playMainVideoWhenVpaidFails(403); return false; } playerInstance.domRef.player.loop = false; playerInstance.domRef.player.removeAttribute('controls'); //Remove the default Controls playerInstance.vpaidCallbackListenersAttach(); const mode = (playerInstance.fullscreenMode ? 'fullscreen' : 'normal'); playerInstance.vpaidAdUnit.initAd(adWidth, adHeight, mode, 3000, creativeData, environmentVars); playerInstance.toggleLoader(false); playerInstance.adList[adListId].played = true; playerInstance.adFinished = false; }; playerInstance.loadVpaid(adListId, vastSettings.staticResource); playerInstance.debugMessage('create non linear vpaid'); }; // ADS playerInstance.createNonLinearBoard = (adListId) => { const vastSettings = playerInstance.adPool[adListId]; playerInstance.adList[adListId].played = true; const playerWidth = playerInstance.domRef.player.clientWidth; const playerHeight = playerInstance.domRef.player.clientHeight; const board = document.createElement('div'); const vAlign = (playerInstance.adList[adListId].vAlign) ? playerInstance.adList[adListId].vAlign : playerInstance.nonLinearVerticalAlign; const creative = new Image(); creative.src = vastSettings.staticResource; creative.id = 'fluid_nonLinear_imgCreative_' + adListId + '_' + playerInstance.videoPlayerId; creative.onerror = function () { playerInstance.adList[adListId].error = true; playerInstance.announceError(500); }; creative.onload = function () { let origWidth; let origHeight; let newBannerWidth; let newBannerHeight; //Set banner size based on the below priority // 1. adList -> roll -> size // 2. VAST XML width/height attriubute (VAST 3.) // 3. VAST XML static resource dimension if (typeof playerInstance.adList[adListId].size !== 'undefined') { origWidth = playerInstance.adList[adListId].size.split('x')[0]; origHeight = playerInstance.adList[adListId].size.split('x')[1]; } else if (vastSettings.dimension.width && vastSettings.dimension.height) { origWidth = vastSettings.dimension.width; origHeight = vastSettings.dimension.height; } else { origWidth = creative.width; origHeight = creative.height; } if (origWidth > playerWidth) { newBannerWidth = playerWidth - 5; newBannerHeight = origHeight * newBannerWidth / origWidth; } else { newBannerWidth = origWidth; newBannerHeight = origHeight; } if (playerInstance.adList[adListId].roll !== 'onPauseRoll') { //Show the board only if media loaded document.getElementById('fluid_nonLinear_' + adListId).style.display = ''; } const img = document.getElementById(creative.id); img.width = newBannerWidth; img.height = newBannerHeight; playerInstance.trackSingleEvent('impression'); }; board.id = 'fluid_nonLinear_' + adListId; board.className = 'fluid_nonLinear_' + vAlign; board.className += ' fluid_nonLinear_ad'; board.innerHTML = creative.outerHTML; board.style.display = 'none'; //Bind the Onclick event board.onclick = function () { if (typeof vastSettings.clickthroughUrl !== 'undefined') { window.open(vastSettings.clickthroughUrl); } //Tracking the NonLinearClickTracking events if (typeof vastSettings.clicktracking !== 'undefined') { playerInstance.callUris([vastSettings.clicktracking]); } }; if (typeof vastSettings.clickthroughUrl !== 'undefined') { board.style.cursor = 'pointer'; } const closeBtn = document.createElement('div'); closeBtn.id = 'close_button_' + playerInstance.videoPlayerId; closeBtn.className = 'close_button'; closeBtn.innerHTML = ''; closeBtn.title = playerInstance.displayOptions.layoutControls.closeButtonCaption; const tempadListId = adListId; closeBtn.onclick = function (event) { this.parentElement.remove(); if (typeof event.stopImmediatePropagation !== 'undefined') { event.stopImmediatePropagation(); } playerInstance.adFinished = true; clearInterval(playerInstance.nonLinearTracking); //if any other onPauseRoll then render it if (playerInstance.adList[tempadListId].roll === 'onPauseRoll' && playerInstance.onPauseRollAdPods[0]) { const getNextOnPauseRollAd = playerInstance.onPauseRollAdPods[0]; playerInstance.createBoard(getNextOnPauseRollAd); playerInstance.currentOnPauseRollAd = playerInstance.onPauseRollAdPods[0]; delete playerInstance.onPauseRollAdPods[0]; } return false; }; board.appendChild(closeBtn); playerInstance.domRef.player.parentNode.insertBefore(board, playerInstance.domRef.player.nextSibling); }; // ADS /** * Adds a nonLinear static Image banner * * currently only image/gif, image/jpeg, image/png supported */ playerInstance.createBoard = (adListId) => { const vastSettings = playerInstance.adPool[adListId]; // create nonLinear Vpaid // create nonLinear regular if (vastSettings.vpaid) { playerInstance.hardStopVpaidAd(''); playerInstance.createVpaidNonLinearBoard(adListId); } else { if (typeof vastSettings.staticResource === 'undefined' || playerInstance.supportedStaticTypes.indexOf(vastSettings.creativeType) === -1) { //Couldn’t find NonLinear resource with supported type. playerInstance.adList[adListId].error = true; if (!playerInstance.vastOptions || typeof playerInstance.vastOptions.errorUrl === 'undefined') { playerInstance.announceLocalError(503); } else { playerInstance.announceError(503); } return; } playerInstance.createNonLinearBoard(adListId); } }; playerInstance.closeNonLinear = (adListId) => { const element = document.getElementById('fluid_nonLinear_' + adListId); if (element) { element.remove(); } }; playerInstance.rollGroupContainsLinear = (groupedRolls) => { let found = false; for (let i = 0; i < groupedRolls.length; i++) { if (playerInstance.adList[groupedRolls[i].id].adType && playerInstance.adList[groupedRolls[i].id].adType === 'linear') { found = true; break; } } return found; }; playerInstance.rollGroupContainsNonlinear = (groupedRolls) => { let found = false; for (let i = 0; i < groupedRolls.length; i++) { if (playerInstance.adList[groupedRolls[i].id].adType.toLowerCase() === 'nonlinear') { found = true; break; } } return found; }; playerInstance.preRollFail = () => { const preRollsLength = playerInstance.preRollAdPodsLength; playerInstance.preRollVastResolved++; if (playerInstance.preRollVastResolved === preRollsLength) { playerInstance.preRollAdsPlay(); } }; playerInstance.preRollSuccess = () => { const preRollsLength = playerInstance.preRollAdPodsLength; playerInstance.preRollVastResolved++; if (playerInstance.preRollVastResolved === preRollsLength) { playerInstance.preRollAdsPlay(); } }; playerInstance.preRollAdsPlay = () => { const time = 0; const adListIds = playerInstance.preRollAdPods; const adsByType = { linear: [], nonLinear: [] }; playerInstance.firstPlayLaunched = true; for (let index = 0; index < adListIds.length; index++) { if (playerInstance.adList[adListIds[index]].played === true) { return } if (playerInstance.adList[adListIds[index]].adType === 'linear') { adsByType.linear.push(adListIds[index]); } if (playerInstance.adList[adListIds[index]].adType === 'nonLinear') { adsByType.nonLinear.push(adListIds[index]); playerInstance.scheduleTask({time: time, playRoll: 'midRoll', adListId: adsByType.nonLinear.shift()}); } } if (adsByType.linear.length > 0) { playerInstance.toggleLoader(false); playerInstance.playRoll(adsByType.linear); } else { playerInstance.playMainVideoWhenVastFails(900); } }; playerInstance.preRoll = (event) => { const vastObj = event.vastObj; playerInstance.domRef.player.removeEventListener(event.type, playerInstance.preRoll); const adListId = []; adListId[0] = event.type.replace('adId_', ''); const time = 0; if (playerInstance.adList[adListId[0]].played === true) { return; } playerInstance.preRollAdPods.push(adListId[0]); playerInstance.preRollSuccess(vastObj); }; playerInstance.createAdMarker = (adListId, time) => { const markersHolder = document.getElementById(playerInstance.videoPlayerId + '_ad_markers_holder'); const adMarker = document.createElement('div'); adMarker.id = 'ad_marker_' + playerInstance.videoPlayerId + "_" + adListId; adMarker.className = 'fluid_controls_ad_marker'; adMarker.style.left = (time / playerInstance.mainVideoDuration * 100) + '%'; if (playerInstance.isCurrentlyPlayingAd) { adMarker.style.display = 'none'; } markersHolder.appendChild(adMarker); }; playerInstance.hideAdMarker = (adListId) => { const element = document.getElementById('ad_marker_' + playerInstance.videoPlayerId + "_" + adListId); if (element) { element.style.display = 'none'; } }; playerInstance.showAdMarkers = () => { const markersHolder = document.getElementById(playerInstance.videoPlayerId + '_ad_markers_holder'); const adMarkers = markersHolder.getElementsByClassName('fluid_controls_ad_marker'); const idPrefix = 'ad_marker_' + playerInstance.videoPlayerId + "_"; for (let i = 0; i < adMarkers.length; ++i) { const item = adMarkers[i]; const adListId = item.id.replace(idPrefix, ''); if (playerInstance.adList[adListId].played === false) { item.style.display = ''; } } }; playerInstance.hideAdMarkers = () => { const markersHolder = document.getElementById(playerInstance.videoPlayerId + '_ad_markers_holder'); const adMarkers = markersHolder.getElementsByClassName('fluid_controls_ad_marker'); for (let i = 0; i < adMarkers.length; ++i) { const item = adMarkers[i]; item.style.display = 'none'; } }; playerInstance.midRoll = (event) => { playerInstance.domRef.player.removeEventListener(event.type, playerInstance.midRoll); const adListId = event.type.replace('adId_', ''); if (playerInstance.adList[adListId].played === true) { return; } let time = playerInstance.adList[adListId].timer; if (typeof time == 'string' && time.indexOf("%") !== -1) { time = time.replace('%', ''); time = Math.floor(playerInstance.mainVideoDuration / 100 * time); } if (playerInstance.displayOptions.vastOptions.showProgressbarMarkers && playerInstance.adList[adListId].adType === "nonLinear") { playerInstance.createAdMarker(adListId, time); } playerInstance.scheduleTask({ time: time, playRoll: 'midRoll', adListId: adListId }); }; playerInstance.postRoll = (event) => { playerInstance.domRef.player.removeEventListener(event.type, playerInstance.postRoll); const adListId = event.type.replace('adId_', ''); playerInstance.scheduleTask({ time: Math.floor(playerInstance.mainVideoDuration), playRoll: 'postRoll', adListId: adListId }); }; playerInstance.onPauseRoll = (event) => { playerInstance.domRef.player.removeEventListener(event.type, playerInstance.onPauseRoll); const adListId = event.type.replace('adId_', ''); if (playerInstance.adList[adListId].adType === 'nonLinear') { if (!playerInstance.adPool.hasOwnProperty(adListId) || playerInstance.adPool[adListId].error === true) { playerInstance.announceLocalError(101); return; } //var playerWrapper = document.getElementById('fluid_video_wrapper_' + playerInstance.videoPlayerId); const nonLinearAdExists = document.getElementsByClassName('fluid_nonLinear_ad')[0]; if (!nonLinearAdExists) { playerInstance.createBoard(adListId); playerInstance.currentOnPauseRollAd = adListId; let onPauseAd = document.getElementById('fluid_nonLinear_' + adListId); if (onPauseAd) { onPauseAd.style.display = 'none'; } } else { playerInstance.onPauseRollAdPods.push(adListId); } } }; /** * Check if player has a valid nonLinear onPause Ad */ playerInstance.hasValidOnPauseAd = () => { // TODO should be only one. Add validator to allow only one onPause roll const onPauseAd = playerInstance.findRoll('onPauseRoll'); return (onPauseAd.length !== 0 && playerInstance.adList[onPauseAd[0]] && playerInstance.adList[onPauseAd[0]].error === false); }; /** * Hide/show nonLinear onPause Ad */ playerInstance.toggleOnPauseAd = () => { playerInstance.toggleLoader(false); if (playerInstance.hasValidOnPauseAd() && !playerInstance.isCurrentlyPlayingAd) { const onPauseRoll = playerInstance.findRoll('onPauseRoll'); let adListId; if (playerInstance.currentOnPauseRollAd !== '') { adListId = playerInstance.currentOnPauseRollAd; } else { adListId = onPauseRoll[0]; } playerInstance.vastOptions = playerInstance.adPool[adListId]; const onPauseAd = document.getElementById('fluid_nonLinear_' + adListId); if (onPauseAd && playerInstance.domRef.player.paused) { setTimeout(function () { onPauseAd.style.display = 'flex'; playerInstance.adList[adListId].played = false; playerInstance.trackingOnPauseNonLinearAd(adListId, 'start'); }, 500); } else if (onPauseAd && !playerInstance.domRef.player.paused) { onPauseAd.style.display = 'none'; playerInstance.adFinished = true; playerInstance.trackingOnPauseNonLinearAd(adListId, 'complete'); } } }; /** * Helper function for tracking onPause Ads */ playerInstance.trackingOnPauseNonLinearAd = (adListId, status) => { if (!playerInstance.adPool.hasOwnProperty(adListId) || playerInstance.adPool[adListId].error === true) { playerInstance.announceLocalError(101); return; } playerInstance.vastOptions = playerInstance.adPool[adListId]; playerInstance.trackSingleEvent(status); }; playerInstance.getLinearAdsFromKeyTime = (keyTimeLinearObj) => { const adListIds = []; for (let i = 0; i < keyTimeLinearObj.length; i++) { if (playerInstance.adList[keyTimeLinearObj[i].adListId].played === false) { adListIds.push(keyTimeLinearObj[i].adListId); } } return adListIds; }; playerInstance.adKeytimePlay = (keyTime) => { if (!playerInstance.timerPool[keyTime] || playerInstance.isCurrentlyPlayingAd) { return; } const timerPoolKeytimeCloseStaticAdsLength = playerInstance.timerPool[keyTime]['closeStaticAd'].length; const timerPoolKeytimeLinearAdsLength = playerInstance.timerPool[keyTime]['linear'].length; const timerPoolKeytimeNonlinearAdsLength = playerInstance.timerPool[keyTime]['nonLinear'].length; // remove the item from keytime if no ads to play if (timerPoolKeytimeCloseStaticAdsLength === 0 && timerPoolKeytimeLinearAdsLength === 0 && timerPoolKeytimeNonlinearAdsLength === 0) { delete playerInstance.timerPool[keyTime]; return; } // Task: close nonLinear ads if (timerPoolKeytimeCloseStaticAdsLength > 0) { for (let index = 0; index < timerPoolKeytimeCloseStaticAdsLength; index++) { const adListId = playerInstance.timerPool[keyTime]['closeStaticAd'][index].closeStaticAd; if (playerInstance.adList[adListId].played === true) { playerInstance.completeNonLinearStatic(adListId); } } // empty closeStaticAd from the timerpool after closing playerInstance.timerPool[keyTime]['closeStaticAd'] = []; } // Task: play linear ads if (timerPoolKeytimeLinearAdsLength > 0) { const adListIds = playerInstance.getLinearAdsFromKeyTime(playerInstance.timerPool[keyTime]['linear']); if (adListIds.length > 0) { playerInstance.playRoll(adListIds); // empty the linear ads from the timerpool after played playerInstance.timerPool[keyTime]['linear'] = []; // return after starting video ad, so non-linear will not overlap return; } } // Task: play nonLinear ads if (timerPoolKeytimeNonlinearAdsLength > 0) { for (let index = 0; index < timerPoolKeytimeNonlinearAdsLength; index++) { const adListId = playerInstance.timerPool[keyTime]['nonLinear'][index].adListId; const vastOptions = playerInstance.adPool[adListId]; // we are not supporting nonLinear ads in cardBoard mode if (playerInstance.adList[adListId].played === false && !playerInstance.displayOptions.layoutControls.showCardBoardView) { playerInstance.createNonLinearStatic(adListId); if (playerInstance.displayOptions.vastOptions.showProgressbarMarkers) { playerInstance.hideAdMarker(adListId); } // delete nonLinear after playing playerInstance.timerPool[keyTime]['nonLinear'].splice(index, 1); // return after starting non-linear ad, so multiple non-linear will not overlap // unplayed non-linear will appear if user seeks back to the time :) return; } } } }; playerInstance.adTimer = () => { if (!!playerInstance.isTimer) { return; } playerInstance.isTimer = !playerInstance.isTimer; playerInstance.timer = setInterval( function () { const keyTime = Math.floor(playerInstance.getCurrentTime()); playerInstance.adKeytimePlay(keyTime) }, 800); }; // ADS playerInstance.scheduleTask = (task) => { if (!playerInstance.timerPool.hasOwnProperty(task.time)) { playerInstance.timerPool[task.time] = {linear: [], nonLinear: [], closeStaticAd: []}; } if (task.hasOwnProperty('playRoll') && playerInstance.adList[task.adListId].adType === 'linear') { playerInstance.timerPool[task.time]['linear'].push(task); } else if (task.hasOwnProperty('playRoll') && playerInstance.adList[task.adListId].adType === 'nonLinear') { playerInstance.timerPool[task.time]['nonLinear'].push(task); } else if (task.hasOwnProperty('closeStaticAd')) { playerInstance.timerPool[task.time]['closeStaticAd'].push(task); } }; // ADS playerInstance.switchToMainVideo = () => { playerInstance.debugMessage('starting main video'); playerInstance.domRef.player.src = playerInstance.originalSrc; playerInstance.initialiseStreamers(); const newCurrentTime = (typeof playerInstance.domRef.player.mainVideoCurrentTime !== 'undefined') ? Math.floor(playerInstance.domRef.player.mainVideoCurrentTime) : 0; if (playerInstance.domRef.player.hasOwnProperty('currentTime')) { playerInstance.domRef.player.currentTime = newCurrentTime; } if (playerInstance.displayOptions.layoutControls.loop) { playerInstance.domRef.player.loop = true; } playerInstance.setCurrentTimeAndPlay(newCurrentTime, playerInstance.autoplayAfterAd); playerInstance.isCurrentlyPlayingAd = false; playerInstance.deleteVastAdElements(); playerInstance.adFinished = true; playerInstance.displayOptions.vastOptions.vastAdvanced.vastVideoEndedCallback(); playerInstance.vastOptions = null; playerInstance.setBuffering(); const progressbarContainer = document.getElementById(playerInstance.videoPlayerId + '_fluid_controls_progress_container'); if (progressbarContainer !== null) { const backgroundColor = (playerInstance.displayOptions.layoutControls.primaryColor) ? playerInstance.displayOptions.layoutControls.primaryColor : "white"; const currentProgressBar = playerInstance.domRef.player.parentNode.getElementsByClassName('fluid_controls_currentprogress'); for (let i = 0; i < currentProgressBar.length; i++) { currentProgressBar[i].style.backgroundColor = backgroundColor; } } playerInstance.domRef.player.removeEventListener('ended', playerInstance.onVastAdEnded); if (playerInstance.displayOptions.vastOptions.showProgressbarMarkers) { playerInstance.showAdMarkers(); } if (playerInstance.hasTitle()) { const title = document.getElementById(playerInstance.videoPlayerId + '_title'); title.style.display = 'inline'; } }; // ADS playerInstance.getNextAdPod = () => { const getFirstUnPlayedAd = false; let adListId = null; // if temporaryAdPods is not empty if (playerInstance.temporaryAdPods.length > 0) { const temporaryAdPods = playerInstance.temporaryAdPods.shift(); adListId = temporaryAdPods.id; } return adListId; }; // ADS playerInstance.checkForNextAd = () => { const avai