ARTICLES

Expand Accordion Item By URL Anchor Hash In Bricks Builder

Want to expand a specific accordion item automatically when visitor click on a link from another page? Some WordPress plugins or themes will handle it for you but not in Bricks theme version 1.3.7 yet.

Tutorial Environment Setup

Below are my tutorial environment setup:

  • Bricks theme v1.3.7 (Tested up to v1.5 rc)
  • WordPress 5.9.2
  • PHP 7.4
  • Open LiteSpeed Server
  • All custom codes in this tutorial place in theme / child theme functions.php

Understand How Bricks Accordion Works

We can easily create an accordion in Bricks. Just drag and drop the Accordion element from General category. After apply some CSS styles, a simple accordion with 2 items will be showing like this.

Accordion in General Category (Bricks Builder).
Accordion in General Category (Bricks Builder).
A simple accordion after applied some css styles.
A simple accordion after applied some css styles.

If we inspect the accordion in frontend, basically it’s just a click event listener on a div with class accordion-title-wrapper and perform below tasks:

  • Find all other accordion items and close them (included animation and class removing)
  • Toggle the current accordion item (included animation and class toggling)

Click event on accordion-title-wrapper class.
Click event on accordion-title-wrapper class.

After we knew how Bricks accordion works, we can either rewrite the same tasks or trigger the click event via our custom JavaScript. I prefer to trigger the click event instead of rewrite the logic and who knows the classes might be changed by Bricks team in future update right?

Objective And Plan

Okay, now we need to come out with a plan to achieve our main objective. We will assume the flow run like this:

  1. Visitor click a link in page A with hash tag. The hash tag is targeting a specific accordion item. Example: https://itchycode.com/page-b/#accordion-item-2
  2. Upon reaching page B (https://itchycode.com/page-b), our JavaScript needs to check if there is hash in the uri.
  3. If hash found in uri, check if the target element exists in the current page. Scroll the page to the element and expand it if the element is an accordion item.

Sounds logic and simple right? Let’s get our hands dirty next.

Step 1 Add Id For Accordion Item

Generally, when hashtag exists on uri, major browsers will auto scrolls to the element if the ID matched with the hashtag. Let’s say you got a div with ID my-div, if you access this page with #my-div in the suffix of the url, your browser should scrolls to this div automatically. (Yeap, the scrolls effect is instant and without animation, I will not cover that in this tutorial.)

Using the same concept, we can just set unique IDs for each of our accordion items and the auto scroll should works!

For the current Bricks Builder (v1.3.7), there is no way to add ID for accordion items via Bricks editor. I will do it by using bricks/element/render_attributes filter.

Updated 2022 May 25: In Bricks Builder (v1.4), bricks/element/render_attributes filter only accept 4 parameters and $is_frontend was removed. Already reported in Bricks Forum. Please remember to change accordingly to avoid error.

Updated 2022 Aug 02: In Bricks Builder (v1.5rc), just left 3 parameters, 3rd parameter will be $element itself.

<?php

add_filter( 'bricks/element/render_attributes', 'itchycode_add_ids_for_accordion_items', 20, 3 );

function itchycode_add_ids_for_accordion_items( $attributes, $key, $element ){

	// Only target accordion and frontend, bricks_is_frontend() is a helper function by Bricks theme
	if( $element->name !== 'accordion' || !bricks_is_frontend() ) return $attributes;

	// Now loop through the accordion items
	foreach ( $element->settings['accordions'] as $index => $accordion ) {

		// This is to skip the foreach loop if the id insertion already performed in previous filter execution
		if( isset($attributes["accordion-title-{$index}"]["accordion-hash"]) &&  isset($attributes["accordion-title-{$index}"]["id"]) ) {
			break;
		}

		// I will generate the id based on our accordion title.
		// Lowercase the title, remove all special characters and replace space with dash.
		// Title: How to be rich in 3 days?
		// Id: how-to-be-rich-in-3-days
		// Final URI: https://mywebsite.com/page-B/#how-to-be-rich-in-3-days
		// This is the previous code, decided to use WordPress sanitize_title() to achieve the same output. Old: $id = preg_replace('/[^A-Za-z0-9\-]/', '', str_replace(' ', '-', strtolower($accordion['title']) ) );
		$id = sanitize_title( $accordion['title'] );

		// Add id to the correct element in frontend
		$attributes["accordion-title-{$index}"]["id"] = $id;
	}
	
	return $attributes;
};

?>

Please read through the comments and you will be understand it. The important is on line 24, the way I generate the ID. This will determine how we set the hashtag in uri later.

Once you have applied the above filter, you will be able to see the ID generated as expected.

Id generated on each accordion item based on Accordion Title set through Bricks Builder.
ID generated on each accordion item based on Accordion Title set through Bricks Builder.

To test it out, just navigate to the page url with suffix #accordion-item-2, browser should auto scrolls to the specific accordion item. Please be careful on typo mistake, it could lead you to unnecessary troubleshooting time. If this works, let’s continue with the JavaScript part.

Step 2 JavaScript To Detect URI Hash On Page Loaded

To embed your own JavaScript, you can navigate through WordPress wp-admin backend “Bricks” > “Settings” > “Custom Code” tab > “Body (footer) scripts”. You could do it by using wp_enqueue_scripts action hook and wp_enqueue_script function too. In this tutorial, I will just use wp_footer action hook to print out my JavaScript like example below.

<?php

add_action( 'wp_footer', 'itchycode_accordion_enhance_javascript' );

function itchycode_accordion_enhance_javascript(){

	?>
	<script>
	(()=>{

		document.addEventListener( 'DOMContentLoaded', ()=>{
				console.log(`Itchycode Accordion Enhance Javascript`);
		})

	})()
	</script>

	<?php
}

?>

Okay, now let’s declare a function to trigger the Bricks click accordion event.

const triggerAccordionItem = ()=>{
	// Get the current uri hashtag
	urlHash = window.location.hash;
	
	// Do nothing if urlHash is empty or hash without text
	if( urlHash == '' || urlHash.split('#').length === 1 ) return;
	
	// Get the id from the hashtag
	let id = urlHash.split('#')[1];
	
	// Find the id element
	let targetAccordionTitle = document.getElementById(id);
	
	if( targetAccordionTitle ) {
		
		// Find the div with class accordion-title-wrapper, if found then click it!
		targetAccordionTitle.closest('.accordion-title-wrapper')?.click();

		// Uncomment below for troubleshooting
		// console.log('Click Triggered', targetAccordionTitle.closest('.accordion-title-wrapper') );

	}
}

// Just execute the function by uncomment it
// triggerAccordionItem();
// But you will notice it's not working as expected....

Alright, the function is ready, but how and when to execute it? Just simply execute triggerAccordionItem() after the declaration will do. However, we still need to do a little dirty tricky code to delay the execution because the Bricks accordion click event actually not loaded yet. Hence, the trigger on line 17 do nothing even the hash found and accordion title wrapper targeted correctly.

If you want to test it, just uncomment line 20 and line 26. You will be able to see actually the log will be printed through developer console tab. But the accordion item not expand.

Hashtag exists, accordion-title-wrapper element found, click triggered. But not accordion item not expand.
Hashtag exists, accordion-title-wrapper element found, click triggered. But not accordion item not expand.

To overcome this, I will use setTimeout to delay for the function execution. (Hopefully someone can suggest me a better way)

// If you want to play safe, just increase the delay time maybe to 300
// If your Bricks JavaScript deliver slow or delay due to some reasons, you should increase the time too
setTimeout( triggerAccordionItem, 150);

So, the final code for JavaScript part should looks like below.

<?php

add_action( 'wp_footer', 'itchycode_accordion_enhance_javascript' );

function itchycode_accordion_enhance_javascript(){

	?>
	<script>
	(()=>{

		document.addEventListener( 'DOMContentLoaded', ()=>{
		
			const triggerAccordionItem = ()=>{
				// Get the current uri hashtag
				urlHash = window.location.hash;
				
				// Do nothing if urlHash is empty or hash without text
				if( urlHash == '' || urlHash.split('#').length === 1 ) return;
				
				// Get the id from the hashtag
				let id = urlHash.split('#')[1];
				
				// Find the id element
				let targetAccordionTitle = document.getElementById(id);
				
				if( targetAccordionTitle ) {
					
					// Find the div with class accordion-title-wrapper, if found then click it!
					targetAccordionTitle.closest('.accordion-title-wrapper')?.click();

					// Uncomment below for troubleshooting
					// console.log('Click Triggered', targetAccordionTitle.closest('.accordion-title-wrapper') );

				}
			}
			
			setTimeout( triggerAccordionItem, 150);
			
		})

	})()
	</script>

	<?php
}

?>

Finally, automatically expand Bricks accordion item based on url anchor hash completed successfully!!

Conclusion

There might be more different ways to achieve the same result, such as create a custom element, use alternate widgets or plugins. This tutorial is just one of them, and I hope my explanation is clear and able to help you out. Hopefully Bricks theme will be adding more features, more action and filter hooks in the future.

As usual, just drop me message if need someone for WordPress customization, just drop me a message. If you found some interested topics or discussions, welcome to shot me message too!

Action & Filter hooks used in this tutorial:

  • wp_footer
  • bricks/element/render_attributes
  • bricks_is_frontend
  • sanitize_title
  • About Author

    Jenn@Itchycode
    I like to solve problems by coding. I like websites, web applications and everything viewable from browser. Knowledge sharing can grows my confidence. A simple "thank you" will make my day :)
    More about me

Subscribe For Notification

Get notification whenever new article published.
Subscription Form

Discussion

COMMENT
Be the first to drop a comment.
New comment
Comment Form