import customEvent from '../utils/customEvent';
/**
* StreamPicker - loads a new stream upon dropdown selection.
*
* @module StreamPicker
* @prop {object} selectors - DOM query selectors
* @prop {object} states - css classes representing states of the player and stream picker control
* @prop {boolean} isOpened - whether or not the select dropdown is opened
* @prop {HTMLElement} $player - the video player DOM element
* @prop {HTMLElement} $control - the stream picker control DOM element
*/
const StreamPicker = {
selectors: {
control: '.l-videoHub__control',
button: '.l-videoHub__button',
ui: '.l-videoHub__selectionList, a',
dropdown: '.l-videoHub__selectionList',
videoPlayer: '#GNVideo_jwPlayerContainer',
videoContainer: '.jwplayer-container',
},
states: {
playing: 'jw-state-playing',
inactive: 'jw-flag-user-inactive',
fadeOut: 'is-faded-out',
fadeIn: 'is-faded-in',
animated: 'is-animated',
},
isOpened: false,
$player: false,
/**
* Bind change event to Stream picker dropdown,
* Show / hide the stream picker control with video player controls.
*
* @method init
*/
init() {
const $controls = document.querySelectorAll( this.selectors.control );
if ( $controls ) {
[].forEach.call( $controls, ( $control ) => {
const $picker = $control.querySelector( this.selectors.dropdown );
const $ui = $control.querySelectorAll( this.selectors.ui );
// Add change listener to dropdown.
$picker.addEventListener( 'change', ( evt ) => {
/* eslint-disable camelcase */
/* global gn_analytics */
if ( typeof ( gn_analytics ) !== 'undefined' && typeof ( gn_analytics.Analytics ) !== 'undefined' ) {
gn_analytics.Analytics.track(['adobe'], {
eventType: 'click',
action: 'gnlive stream select',
target: false,
});
}
/* eslint-enable camelcase */
// navigate to destination page on timeout to allow tracking call to go through.
setTimeout( () => {
window.location.href = evt.target.options[evt.target.selectedIndex].value;
}, 500 );
});
// Show the contorl when picker is in focus.
$picker.addEventListener( 'focus', () => {
$control.dataset.focused = 'true'; // eslint-disable-line no-param-reassign
this.show( $control );
});
// Show the picker when moused over.
$control.addEventListener( 'mouseover', () => {
this.show( $control );
});
// On mouseout, determine whether to show or hide the contorl based on player state.
$control.addEventListener( 'mouseout', () => {
this.showOrHide();
});
// Show the contorl when button / dropdown is in focus.
[].forEach.call( $ui, ( $elem ) => {
$elem.addEventListener( 'focus', () => {
$control.dataset.focused = 'true'; // eslint-disable-line no-param-reassign
this.show( $control );
});
});
// Listen to click / blur events to show / hide the animated control.
const isAnimated = $control.classList.contains( this.states.animated );
$picker.addEventListener( 'click', () => {
$control.dataset.opened = 'true' !== $control.dataset.opened; // eslint-disable-line no-param-reassign
if ( 'true' !== $control.dataset.opened ) {
if ( isAnimated ) {
this.showOrHide();
}
}
});
// Show the contorl when button / dropdown is in focus.
if ( isAnimated ) {
[].forEach.call( $ui, ( $elem ) => {
$elem.addEventListener( 'blur', () => {
$control.dataset.opened = false; // eslint-disable-line no-param-reassign
$control.dataset.focused = false; // eslint-disable-line no-param-reassign
this.showOrHide();
});
});
}
// Listen to video player div attribute change when the video player is ready.
window.addEventListener( customEvent.VIDEO_PLAYER_READY, () => {
const observer = new MutationObserver( ( mutationsList ) => {
// Show / hide stream picker control based on player state,
// so that it shows / hides at the same time as other video player controls.
mutationsList.forEach( () => {
this.showOrHide();
});
});
this.$player = document.querySelector( this.selectors.videoPlayer );
observer.disconnect();
observer.observe( this.$player, { attributes: true, childList: false, subtree: false });
});
});
}
},
/**
* Show / hide the animated stream picker control based on the video player state.
*
* @method showOrHide
*/
showOrHide() {
const $animatedControls = document.querySelectorAll( `${this.selectors.control}.${this.states.animated}` );
[].forEach.call( $animatedControls, ( $control ) => {
// Bail if the stream picker is currently active.
if ( 'true' === $control.dataset.opened || 'true' === $control.dataset.focused ) {
return;
}
if ( this.$player.classList && this.$player.classList.contains( this.states.playing )
&& this.$player.classList.contains( this.states.inactive ) ) {
this.hide( $control );
} else {
this.show( $control );
}
});
},
/**
* Show the animated stream picker control.
*
* @method hide
*/
hide( $control ) {
$control.classList.add( this.states.fadeOut );
$control.classList.remove( this.states.fadeIn );
},
/**
* Hide the animated stream picker control.
*
* @method show
*/
show( $control ) {
$control.classList.add( this.states.fadeIn );
$control.classList.remove( this.states.fadeOut );
},
};
export default StreamPicker;