Untitled
unknown
plain_text
a year ago
12 kB
11
Indexable
import { assignEventAction } from '../utils/analytics';
import { getSelectedStateFromLocalStorage } from '../utils/local-storage';
/**
* Tabs
*/
export default class BlackstonePerformanceData {
/**
* Component Constructor.
*/
constructor() {
this.blocks = Array.from( document.querySelectorAll( '.performance-data' ) );
this.selectedState = getSelectedStateFromLocalStorage();
// Bail if tabs block is not on page
if ( ! this.blocks.length ) {
return;
}
this.blocks.forEach( block => this.initBlock( block ) );
}
/**
* Initialize the block.
*/
initBlock( block ) {
const select = block.querySelector( '.performance-data__select' );
const dropdownHeader = block.querySelector( '.dropdown-header' );
const dropdownButton = block.querySelector( '.dropdown-button' );
const dropdownOptions = Array.from( block.querySelectorAll( '.dropdown-option' ) );
const windowhashdata = window.location.hash ? window.location.hash : ''; // phpcs:ignore WordPressVIPMinimum.JS.Window.location, WordPressVIPMinimum.JS.Window.VarAssignment
if ( select ) {
const options = Array.from( select.querySelectorAll( 'option' ) );
select.addEventListener( 'change', ( e ) => this.selectTab( e, block ) );
document.addEventListener( 'setGatingState', () => {
this.selectedState = getSelectedStateFromLocalStorage();
this.updateTabs( select, options, windowhashdata );
} );
this.updateTabs( select, options );
this.selectTabOnload( block, windowhashdata );
block.dataset.initiallyHidden = false;
if ( block.querySelector( '.is-sticky' ) ) {
this.positionSelectDropdown( block );
}
}else {
if ( dropdownHeader ) {
dropdownHeader.addEventListener( 'click', ( e ) => this.toggleDropdown( e, block ) );
}
if ( dropdownButton ) {
dropdownButton.addEventListener( 'click', ( e ) => this.toggleDropdown( e, block ) );
}
if ( 0 < dropdownOptions.length ) {
dropdownOptions.forEach( option => {
option.addEventListener( 'click', ( e ) => this.selectDropdownOption( e, block ) );
// Add event listener to remove highlighted on hover
option.addEventListener( 'mouseenter', () => {
dropdownOptions.forEach( opt => opt.classList.remove( 'selected' ) );
} );
} );
}
dropdownOptions.forEach( option => {
option.addEventListener( 'mouseenter', ( e ) => this.handleHover( e ) );
} );
document.addEventListener( 'click', ( event ) => {
if ( !event.target.closest( '.dropdown-container' ) ) {
this.closeDropdown( block );
}
} );
document.addEventListener( 'setGatingState', () => {
sendGAEvent = false;
this.selectedState = getSelectedStateFromLocalStorage();
this.updateTabsForDropdown( dropdownOptions, windowhashdata, block, sendGAEvent );
} );
sendGAEvent = true;
block.dataset.initiallyHidden = false;
this.updateTabsForDropdown( dropdownOptions, windowhashdata, block, sendGAEvent );
this.selectTabOnloadForDropdown( block, windowhashdata );
window.addEventListener( 'scroll', () => this.handleScroll( block ) );
}
// Set the initial value of the dropdown button based on priority: hash value, gating state, or default option
const hashValue = windowhashdata ? windowhashdata.replace( '#', '' ).toLowerCase() : null;
let selectedOption = null;
if ( hashValue ) {
selectedOption = dropdownOptions.find( option => option.getAttribute( 'value' ) === hashValue );
}
if ( !selectedOption && this.selectedState ) {
selectedOption = dropdownOptions.find( option => {
const defaultInStates = option.dataset.defaultInStates?.split( ' ' );
return defaultInStates && defaultInStates.includes( this.selectedState );
} );
}
if ( !selectedOption ) {
selectedOption = dropdownOptions[0];
}
if ( selectedOption && dropdownButton ) {
dropdownButton.innerText = selectedOption.innerText;
this.selectDropdownOption( { target: selectedOption, stopPropagation: () => {} }, block );
}
}
toggleDropdown( e, block ) {
e.stopPropagation();
const dropdownOptions = block.querySelector( '.dropdown-options' );
const dropdownContainer = block.querySelector( '.dropdown-container' );
dropdownOptions.classList.toggle( 'show' );
dropdownContainer.classList.toggle( 'selected' );
}
closeDropdown( block ) {
const dropdownOptions = block.querySelector( '.dropdown-options' );
const dropdownContainer = block.querySelector( '.dropdown-container' );
dropdownOptions.classList.remove( 'show' );
dropdownContainer.classList.remove( 'selected' );
}
selectDropdownOption( e, block ) {
e.stopPropagation();
const selected = e.target.getAttribute( 'value' );
const dropdownButton = block.querySelector( '.dropdown-button' );
const target = block.querySelector( `.performance-data-${selected}` );
const items = Array.from( block.querySelectorAll( '.performance-data__item' ) );
const dropdownOptions = Array.from( block.querySelectorAll( '.dropdown-option' ) );
dropdownOptions.forEach( option => {
option.classList.remove( 'selected' );
option.classList.remove( 'hovered' );
} );
// Mark the clicked option as selected
e.target.classList.add( 'selected' );
if ( dropdownButton ) {
dropdownButton.innerText = e.target.innerText;
}
items.forEach( item => item.setAttribute( 'aria-selected', false ) );
if ( target ) {
target.setAttribute( 'aria-selected', true );
}
this.closeDropdown( block );
assignEventAction( e );
}
/**
* Update the tabs (for state change);
*/
updateTabs( select, options, windowhashdata ) {
let defaultOption = null;
if ( this.selectedState ) {
const defaultOptions = options.filter( option => {
const defaultInStates = option.dataset.defaultInStates?.split( ' ' );
return defaultInStates.includes( this.selectedState );
} );
if ( defaultOptions.length && ! windowhashdata ) {
[defaultOption] = defaultOptions;
select.value = defaultOption.value;
const changeEvent = new Event( 'change' );
select.dispatchEvent( changeEvent );
}
}
}
updateTabsForDropdown( dropdownOptions, windowhashdata, block, sendToGA = true ) {
let defaultOption = null;
if ( this.selectedState ) {
const defaultOptions = dropdownOptions.filter( option => {
const defaultInStates = option.dataset.defaultInStates?.split( ' ' );
return defaultInStates && defaultInStates.includes( this.selectedState );
} );
if ( defaultOptions.length && !windowhashdata ) {
[defaultOption] = defaultOptions;
const event= new Event( 'click', { bubbles: true } );
defaultOption.dispatchEvent( event );
const dropdownButton = block.querySelector( '.dropdown-button' );
if( dropdownButton ) {
dropdownButton.innerText = defaultOption.innerText;
}
// Ensure the selected option is highlighted
dropdownOptions.forEach( option => option.classList.remove( 'selected' ) );
defaultOption.classList.add( 'selected' );
}
}
}
/**
* Select Tab Logic.
*/
selectTab( e, block ) {
const selected = e.target.options[ e.target.selectedIndex ].value;
const target = block.querySelector( `.performance-data-${ selected }` );
const items = Array.from( block.querySelectorAll( '.performance-data__item' ) );
// Unselect selected items.
items.forEach( item => item.setAttribute( 'aria-selected', false ) );
// Select target one.
if ( target ) {
target.setAttribute( 'aria-selected', true );
// Remove focus to prevent ipad issue with chart selection.
e.target.blur();
}
/**
* Reset the first performance item chart tab to first.
* 10up/component-tabs does not provide an api for targetting each instance,
* therefore all tabs are updated on the page. `e.isTrusted` ensures it is
* an user action and not occuring as a result of `updateTabs` region updates,
* which causes onload issues.
*/
if ( e.isTrusted ) {
const firstChartTab = target.querySelector( '.tab-item a[role=tab]' );
if ( firstChartTab ) {
firstChartTab.click();
}
}
// Send GTM data
assignEventAction( e );
}
/**
* Scroll to selected class when hash is present .
*/
selectTabOnload( block, windowhashdata ) {
if ( windowhashdata ) {
if ( window.history.scrollRestoration ) {
window.history.scrollRestoration = 'manual';
}
const selecteddata = windowhashdata.replace( '#', '' ).toLowerCase();
const targetdata = block.querySelector( `.performance-data-${ selecteddata }` );
const itemsdata = Array.from( block.querySelectorAll( '.performance-data__item' ) );
const elem = document.querySelector( '.performance-data' );
const isAnchorAvailable = [...document.querySelector( '.performance-data__select' ).options]
.filter( x => x.value === selecteddata )[0];
if ( isAnchorAvailable ) {
isAnchorAvailable.setAttribute( 'selected', true );
//Unselect selected itemsdata.
itemsdata.forEach( item => item.setAttribute( 'aria-selected', false ) );
// Select target one.
if ( targetdata ) {
targetdata.setAttribute( 'aria-selected', true );
}
if ( elem ) {
const yOffset = -100;
const y = elem.getBoundingClientRect().top + window.scrollY + yOffset;
window.scrollTo( {top: y, behavior: 'smooth'} );
}
} else {
this.selectTabOnloadForDropdown( block, windowhashdata );
}
}
}
selectTabOnloadForDropdown( block, windowhashdata ) {
if ( windowhashdata ) {
if ( window.history.scrollRestoration ) {
window.history.scrollRestoration = 'manual';
}
const selecteddata = windowhashdata.replace( '#', '' ).toLowerCase();
const targetdata = block.querySelector( `.performance-data-${selecteddata}` );
const itemsdata = Array.from( block.querySelectorAll( '.performance-data__item' ) );
const elem = document.querySelector( '.performance-data' );
const isDropdownAnchorAvailable = [...block.querySelectorAll( '.dropdown-option' )]
.filter( x => x.getAttribute( 'value' ) === selecteddata )[0];
if ( isDropdownAnchorAvailable ) {
const dropdownHeaderText = block.querySelector( '.dropdown-header .dropdown-button' );
if ( dropdownHeaderText ) {
dropdownHeaderText.innerText = isDropdownAnchorAvailable.innerText;
}
itemsdata.forEach( item => item.setAttribute( 'aria-selected', false ) );
if ( targetdata ) {
targetdata.setAttribute( 'aria-selected', true );
}
if ( elem ) {
const yOffset = -100;
const y = elem.getBoundingClientRect().top + window.scrollY + yOffset;
window.scrollTo( { top: y, behavior: 'smooth' } );
}
}
}
}
/**
* Just triggers a null change event on select dropdown when the page is scrolled without any change in class selector.
*
* @return void
*/
positionSelectDropdown( block ){
const selectElement = block.querySelector( '.performance-data__select' );
document.addEventListener( 'scroll', () => {
const isFocused = ( document.activeElement === selectElement );
if ( isFocused ) {
selectElement.dispatchEvent( new Event( 'change' ) );
}
} );
}
handleScroll( block ) {
const dropdownOptions = document.getElementById( 'dropdown-options' );
const dropdownContainer = document.querySelector( '.dropdown-container' );
if ( dropdownContainer && dropdownContainer.classList.contains( 'selected' ) ) {
dropdownOptions.classList.remove( 'show' );
dropdownContainer.classList.remove( 'selected' );
}
}
handleHover( e ) {
const dropdownOptions = Array.from( document.querySelectorAll( '.dropdown-option' ) );
dropdownOptions.forEach( option => option.classList.remove( 'hovered' ) );
e.target.classList.add( 'hovered' );
}
}Editor is loading...
Leave a Comment