This shortcode dynamically generates a table of contents with proper parent-child nesting based on heading levels (h2
, h3
, etc.) within a specified container, enhancing content navigation for your WordPress posts or pages.
shortcode: [custom_tableofcontents class_name=”.your-custom-container”]
// [custom_tableofcontents class_name=".your-custom-container"] shortcode function custom_table_of_contents_shortcode($atts) { // Set default class as '.post-contents' if not provided in the shortcode $atts = shortcode_atts( array( 'class_name' => '.post-contents', // default container class ), $atts, 'custom_tableofcontents' ); // Output the div for the TOC and the JavaScript ob_start(); ?> <div id="table-of-contents"></div> <script> document.addEventListener("DOMContentLoaded", function() { // Get the container element based on the class_name attribute var contentContainer = document.querySelector("<?php echo esc_attr($atts['class_name']); ?>"); if (!contentContainer) return; // Exit if the container isn't found var headings = contentContainer.querySelectorAll("h2, h3, h4, h5, h6"); var tocContainer = document.getElementById("table-of-contents"); var tocList = document.createElement("ul"); var currentLevel = 2; // Start from h2 var currentList = tocList; // Main list is the root level list headings.forEach(function(heading, index) { var level = parseInt(heading.tagName.substring(1)); // Get the heading level (2, 3, 4, etc.) var anchorId = "toc-heading-" + index; heading.setAttribute("id", anchorId); // Add unique ID to the heading var listItem = document.createElement("li"); var link = document.createElement("a"); link.setAttribute("href", "#" + anchorId); link.textContent = heading.textContent; listItem.appendChild(link); // Adjust list levels based on heading level if (level > currentLevel) { // Create a new nested list var nestedList = document.createElement("ul"); currentList.lastElementChild.appendChild(nestedList); // Nest it in the previous item currentList = nestedList; } else if (level < currentLevel) { // Go back up to the correct level while (level < currentLevel) { currentList = currentList.parentElement.parentElement; currentLevel--; } } currentLevel = level; // Update the current level currentList.appendChild(listItem); // Add the item to the current list }); tocContainer.appendChild(tocList); // Append the final TOC list to the container }); </script> <?php return ob_get_clean(); // Output the HTML and JavaScript } // Register the shortcode add_shortcode('custom_tableofcontents', 'custom_table_of_contents_shortcode');