Untitled
unknown
plain_text
a month ago
18 kB
2
Indexable
Never
In below code we have a line if ( empty( $groupTitles ) ) here we are checking if we have empty group title then performance-data__actions will work else dropdown-container will work so we have javascript code that take performance-data__actions and performance-data__select in javascript so make same changes for dropdown conatiner that takes values from dropdown-group and dropdown-option in javascript so that dropdown condition works smootly. <?php /** * Server-side rendering of the Performance Data Gutenberg Block * * @package blackstone-main/gutenberg */ namespace BlackstoneCore\Gutenberg\Blocks; use function BlackstoneCore\Utility\setup_multiple_gtm_attributes; /** * Performance Data Block Attributes * * @return array Array of block attributes */ function performance_data_atts() { return [ 'title' => [ 'type' => 'string', 'default' => '', ], 'heading' => [ 'type' => 'string', 'default' => 'h2', ], 'margintop' => [ 'type' => 'string', 'default' => '', ], 'marginbottom' => [ 'type' => 'string', 'default' => '', ], 'bringToFront' => [ 'type' => 'boolean', 'default' => false, ], 'sticky' => [ 'type' => 'boolean', 'default' => false, ], 'enableGrp' => [ 'type' => 'boolean', 'default' => false, ], ]; } /** * Performance Data Item Block Attributes * * @return array Array of block attributes */ function performance_data_item_atts() { return [ 'title' => [ 'type' => 'string', 'default' => '', ], 'groupTitle' => [ 'type' => 'string', 'default' => '', ], 'states' => [ 'type' => 'array', 'default' => [], ], ]; } /** * Render the Tabs block HTML * * @param array $attributes Array of Block Attributes registered via Gutenberg * @param string $content InnerBlock content * @return string Block HTML markup for frontend */ function performance_data_html( $attributes, $content ) { $title = $attributes['title'] ? $attributes['title'] : ''; $groupTitle = $attributes['groupTitle'] ? $attributes['groupTitle'] : ''; $heading = $attributes['heading'] ? $attributes['heading'] : 'h2'; $mt = $attributes['margintop'] ? ' mt-' . $attributes['margintop'] : ''; $mb = $attributes['marginbottom'] ? ' mb-' . $attributes['marginbottom'] : ''; $markup = sprintf( '<div class="performance-data%1$s%2$s" data-initially-hidden="false">', esc_attr( $mt ), esc_attr( $mb ) ); $markup .= '<div class="performance-data__inner">'; $className = 'performance-data__toolbar '; if ( !empty( $attributes['sticky'] ) && $attributes['sticky'] === true ) { $className .= 'is-sticky '; } if ( !empty( $attributes['enableGrp'] ) && $attributes['enableGrp'] === true ) { $className .= 'performancedata-toolbar-gt'; } $markup .= '<div class="'.$className.'">'; if ( $title ) { $markup .= '<' . tag_escape( $heading ) . ' class="performance-data__toolbar-title mt-zero mb-zero">'; $markup .= esc_html( $title ); $markup .= '</' . tag_escape( $heading ) . '>'; } $markup .= '<!-- Tabs Placeholder -->'; $markup .= '</div>'; $markup .= '<div class="performance-data__content">'; /* * the content is the html generated from innerBlocks * it is being created from the save method in JS or the render_callback * in php and is sanitized. * * Re sanitizing it through `wp_kses_post` causes * embed blocks to break and other core filters don't apply. * therefore no additional sanitization is done and it is being output as is */ $markup .= $content; $markup .= '</div>'; $markup .= '</div>'; $markup .= '</div>'; return $markup; } /** * Render the Tabs Item block HTML * * @param array $attributes Array of Block Attributes registered via Gutenberg * @param string $content InnerBlock content * @return string Block HTML markup for frontend */ function performance_data_item_html( $attributes, $content ) { $tab_title = ! empty( $attributes['title'] ) ? $attributes['title'] : ''; $markup = '<div class="performance-data__item performance-data-' . sanitize_title_with_dashes( $tab_title ) . '" role="tabpanel" aria-selected="false">'; if ( $content ) { /* * the content is the html generated from innerBlocks * it is being created from the save method in JS or the render_callback * in php and is sanitized. * * Re sanitizing it through `wp_kses_post` causes * embed blocks to break and other core filters don't apply. * therefore no additional sanitization is done and it is being output as is */ $markup .= $content; } $markup .= '</div>'; return $markup; } /** * Add select html tags and custom div attribute being used on the block to fix reusable content issue * * @param array $tags Allowed tags, attributes, and/or entities. * @param string $context Context to judge allowed tags by. Allowed values are 'post'. */ add_filter( 'wp_kses_allowed_html', function( $tags, $context ) { if ( 'post' === $context ) { $tags['select'] = array( 'name' => true, 'class' => true, ); $tags['option'] = array( 'value' => true, 'data-gtm-category' => true, 'data-gtm-label' => true, 'data-gtm-action' => true, ); $tags['div'] = isset( $tags['div'] ) ? $tags['div'] : []; $tags['div'] = array_merge( $tags['div'], [ 'role' => true, 'aria-selected' => true, 'aria' => true, ] ); } return $tags; }, 10, 2 ); /** * Modify block rendering to add tab navigations * * @param string|null $pre_render The pre-rendered content. Default null. * @param array $parsed_block The block being rendered. */ add_filter( 'render_block', function( $block_content, $block ) { if ( 'blackstone/performance-data' === $block['blockName'] ) { if ( $block['innerBlocks'] ) { $groupTitles = array(); foreach( $block['innerBlocks'] as $inner_block ) { $groupTitle = $inner_block['attrs']['groupTitle']; if ( ! empty( $groupTitle ) && ! in_array( $groupTitle, $groupTitles, true ) ) { $groupTitles[] = $groupTitle; } } if ( empty( $groupTitles ) ) { $tabs = '<div class="performance-data__action">'; $tabs .= '<div class="custom-select">'; $tabs .= '<select name="performance-class" class="performance-data__select">'; $has_default_states = ! empty( array_filter( array_map( function( $inner_block ) { return ! empty( $inner_block['attrs']['states'] ); }, $block['innerBlocks'] ) ) ); if ( is_array( $block['innerBlocks'] ) ) { foreach ( $block['innerBlocks'] as $inner_block ) { $title = $inner_block['attrs']['title']; $states = ! empty( $inner_block['attrs']['states'] ) ? $inner_block['attrs']['states'] : []; $id = sanitize_title_with_dashes( $title ); $gtm_atts = setup_multiple_gtm_attributes(array("category"=>"Page Engagement", "action"=>"Filter Click", "label"=>'Performance Filter | ' . esc_attr( $title ), "component_type"=>"Chart tabs", "click_text"=>esc_attr( $title ), "tag_name"=>"Page Engagement Click"), false); $tabs .= '<option ' . $gtm_atts . ' value="' . esc_attr( $id ) . '" data-default-in-states="' . esc_attr( implode( ' ', $states ) ) . '">' . esc_html( $title ) . '</option>'; } } $tabs .= '</select>'; $tabs .= '</div>'; $tabs .= '</div>'; } else { $shareClass = __( 'Share Class', 'blackstone' ); $tabs = '<div class="dropdown-container">'; $tabs .= '<div class="dropdown-header" onclick="toggleDropdown()">'; $tabs .= '<div class="share">'. $shareClass .'</div>'; $tabs .= '<div class="dropdown-button">Select an option</div>'; $tabs .= '</div>'; $has_default_states = ! empty( array_filter( array_map( function( $inner_block ) { return ! empty( $inner_block['attrs']['states'] ); }, $block['innerBlocks'] ) ) ); if ( is_array( $block['innerBlocks'] ) ) { $groupsPerforamcenBars = array(); foreach( $block['innerBlocks'] as $inner_block ) { $groupTitle = trim( $inner_block['attrs']['groupTitle'] ); if ( ! isset( $groupsPerforamcenBars[ $groupTitle ] ) ) { $groupsPerforamcenBars[ $groupTitle ] = array(); } $groupsPerforamcenBars[ $groupTitle ][] = $inner_block; } $tabs .= '<div class="dropdown-options" id="dropdown-options">'; foreach ( $groupsPerforamcenBars as $groupTitle => $group_tabs ) { $tabs .= '<div class="dropdown-group">'; $tabs .= '<div class="dropdown-group-title">'. $groupTitle .'</div>'; foreach ( $group_tabs as $inner_block ) { $title = $inner_block['attrs']['title']; $states = ! empty( $inner_block['attrs']['states'] ) ? $inner_block['attrs']['states'] : []; $id = sanitize_title_with_dashes( $title ); $groupTitles = $inner_block['attrs']['groupTitle'] ? explode("\n", $inner_block['attrs']['groupTitle']) : []; $gtm_atts = setup_multiple_gtm_attributes(array("category"=>"Page Engagement", "action"=>"Filter Click", "label"=>'Performance Filter | ' . esc_attr( $title ), "component_type"=>"Chart tabs", "click_text"=>esc_attr( $title ), "tag_name"=>"Page Engagement Click"), false); $tabs .= '<div class="dropdown-option" onclick="selectOption(\'' . esc_js( $title ) . '\')" ' . $gtm_atts . ' value="' . esc_attr( $id ) . '" data-default-in-states="' . esc_attr( implode( ' ', $states ) ) . '">' . esc_html( $title ) . '</div>'; } $tabs .= '</div>'; } $tabs .= '</div>'; } $tabs .= '</div>'; $tabs .='<script> document.addEventListener("DOMContentLoaded", function() { // Set the initial value of the dropdown button to the first option var firstOption = document.querySelector(".dropdown-option"); var dropdownButton = document.querySelector(".dropdown-button"); if (firstOption) { dropdownButton.innerText = firstOption.innerText; } }); function toggleDropdown() { var dropdownOptions = document.getElementById("dropdown-options"); var dropdownContainer = document.querySelector(".dropdown-container"); dropdownOptions.classList.toggle("show"); dropdownContainer.classList.toggle("selected"); } function selectOption(value) { document.querySelector(".dropdown-button").innerText = value; document.getElementById("dropdown-options").classList.remove("show"); document.querySelector(".dropdown-container").classList.remove("selected"); } // Close the dropdown if the user clicks outside of it window.onclick = function(event) { var dropdownContainer = document.querySelector(".dropdown-container"); var dropdownOptions = document.getElementById("dropdown-options"); if (!event.target.closest(".dropdown-container")) { if (dropdownOptions.classList.contains("show")) { dropdownOptions.classList.remove("show"); dropdownContainer.classList.remove("selected"); } } } </script>'; } // Add custom select. $block_content = str_replace( '<!-- Tabs Placeholder -->', $tabs, $block_content ); $block_content = str_replace( 'data-component="chart-tabs-tab-item-link"', 'data-component="chart-tabs-tab-item-link" data-disable-ga-auto-tracking="true"', $block_content ); if ( $has_default_states ) { $block_content = str_replace( 'data-initially-hidden="false"', 'data-initially-hidden="true"', $block_content ); } // Make first item visible. $block_content = preg_replace( '/role=\"tabpanel\" aria-selected=\"false\"/', 'role="tabpanel" aria-selected="true"', $block_content, 1 ); } } return $block_content; }, 10, 2 ); /** * Add body class whenever Performance data block is available on the page */ add_filter( 'body_class', function( $classes ) { if ( has_block( 'blackstone/performance-data' ) ) { $classes[] = 'has-performance-data-block'; } return $classes; } ); In below javascript code add functionality of dropdwon-container to work smootly as we have performance-data__select make sake for dropdown-option and dropdown-group 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 options = Array.from( select.querySelectorAll( 'option' ) ); const windowhashdata = window.location.hash ? window.location.hash : ''; // phpcs:ignore 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 ); } } /** * 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 ); } } } /** * 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.pageYOffset + 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' ) ); } } ); } }
Leave a Comment