Opening Up A Specific Tab, Toggle, or Accordion Using Elementor

One of the nice things about WPBakery is that you can easily link to and open a specific tab out of the box.  Hopefully Elementor will add this feature in the future, but until they do, here’s some JS code to make it happen, using the tab, toggle, or accordion titles as the anchor links (so that you don’t have to hard-code anything – it just works).  Obviously you will need to enqueue what follows in a separate script, or otherwise include this on your page that has a tab, accordion, or toggle instance.

Note: I modified the original idea for this from https://element.how/elementor-open-specific-tab-toggle-accordion/.  I chose to deviate from the original code both to avoid hard-coding anchor names, as well as to use the same code snippet for tabs, toggles, and accordions, since I never know which of these elements content managers at the University may employ.

				
					<script>

window.addEventListener('load', () => {
    // Delay to ensure page elements are fully loaded
    setTimeout(function () {

        // Scroll offset from the top of the page, adjust this value as needed
        let scrollOffset = 100;

        // Select all titles that could represent accordion items or tabs
        const tabsAccordionToggleTitles = document.querySelectorAll('.e-n-accordion-item-title, .e-n-tab-title, .elementor-tab-title');

        // Function to trigger the title based on the anchor in the URL
        const clickTitleWithAnchor = (anchor) => {
            tabsAccordionToggleTitles.forEach(title => {
                // Check if the title or a related element matches the anchor in the URL
                if (title.querySelector(`#${anchor}`) != null || title.id === anchor || (title.closest('details') && title.closest('details').id === anchor)) {
                    
                    // If the title isn't already expanded or active, trigger a click event
                    if (title.getAttribute('aria-expanded') !== 'true' && !title.classList.contains('elementor-active')) title.click();
                    
                    let timing = 0;
                    let scrollTarget = title;

                    // Adjust the scroll target if the tabs are in a horizontal row
                    if (getComputedStyle(title.closest('.elementor-element')).getPropertyValue('--n-tabs-direction') == 'row') {
                        scrollTarget = title.closest('.elementor-element');
                    }

                    // Add a delay for accordion elements to allow for smooth animation
                    if (title.closest('.e-n-accordion, .elementor-accordion-item, .elementor-toggle-item')) {
                        timing = 400;
                    }

                    // Smoothly scroll to the selected title or element
                    setTimeout(function () {
                        jQuery('html, body').animate({
                            scrollTop: jQuery(scrollTarget).offset().top - scrollOffset,
                        }, 'slow');
                    }, timing);
                }
            });
        };

        // Event listener for any clicks on anchor links
        document.addEventListener('click', (event) => {
            if (event.target.closest('a') && event.target.closest('a').href.includes('#')) {
                const anchor = extractAnchor(event.target.closest('a').href);
                if (anchor && isAnchorInTitles(anchor, tabsAccordionToggleTitles)) {
                    event.preventDefault(); // Prevent default anchor navigation
                    clickTitleWithAnchor(anchor); // Open the corresponding tab or accordion
                }
            }
        });

        // Get the current anchor from the URL and open the corresponding tab/accordion
        const currentAnchor = extractAnchor(window.location.href);
        if (currentAnchor) {
            clickTitleWithAnchor(currentAnchor);
        }

        // Extract the anchor (after the #) from a URL
        function extractAnchor(url) {
            const match = url.match(/#([^?]+)/);
            return match ? match[1] : null;
        };

        // Check if the anchor matches any of the titles in the accordion or tabs
        function isAnchorInTitles(anchor, titles) {
            return Array.from(titles).some(title => {
                return title.querySelector(`#${anchor}`) !== null || title.id === anchor || (title.closest('details') && title.closest('details').id === anchor);
            });
        };

    }, 300); // Delay to ensure all elements are loaded before execution
});
</script>