Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Build Table of Contents in Sidebar of a Genesis Theme
/**
* Scans for <h1> to <h6> HTML tags contained within 'genesis-content' and builds a Table of Contents in the primary
* sidebar.
*
* @summary Dynamically builds a Table of Contents for in page navigation.
* @author Edwin Velez (edwinvelez.net)
*
* @version 1.0.1
*/
'use strict';
// Built-in element ID from the Genesis Framework that contains the content.
let contentContainer = document.getElementById( 'genesis-content' );
// The HTML <section></section> that will contain the table of contents.
let sectionPrimarySidebarToc = document.getElementById( 'sidebar-primary-toc' );
// Available HTML heading tags that could be used in a post.
let containerSelectors = contentContainer.querySelectorAll( 'h1, h2, h3, h4, h5, h6' );
// Loop over all matching selectors found.
for ( let i = 0; i < containerSelectors.length; i++ ) {
buildTableOfContents( containerSelectors[ i ], true );
}
/**
* Builds a Table of Contents based upon an elementList of HTML <h1> to <h6> tags found on a page.
*
* @param headingTitle Existing <h1> to <h6> HTML tags of a page.
* @param addAnchorTag True if <a></a> HTML tags should be applied to the title. Used by internal page linking.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
*
* @version 1.0
*/
function buildTableOfContents ( headingTitle, addAnchorTag = false ) {
let sanitizedTitle = hyphenateText( headingTitle.textContent );
let listItem = document.createElement( 'li' );
// The <ul></ul> tag that will eventually contain the Table of Contents.
let containerHeadings = document.getElementById( 'sidebar-primary-toc-headings' );
listItem.setAttribute( 'class', 'sidebar-primary-toc-heading-title' );
// Should the HTML heading be hyperlinked? Needed for internal page linking.
if ( addAnchorTag ) {
let a = document.createElement( 'a' );
// First assign 'id' attribute to the HTML heading.
headingTitle.setAttribute( 'id', sanitizedTitle );
// Build internal page link tag settings.
a.setAttribute( 'href', '#' + sanitizedTitle );
a.textContent = headingTitle.textContent;
// Add hyperlink capabilities to list item.
listItem.appendChild( a );
} else {
// Add text to list out without hyperlink capabilities.
listItem.textContent = headingTitle.textContent;
}
// Add list item to list.
containerHeadings.appendChild( listItem );
}
/**
* Replaces whitespace of the passed in text value with hyphens (-).
*
* @param dirtyText The text to be sanitized.
* @returns {*} Sanitized Text
*
* @version 1.0
*/
function hyphenateText ( dirtyText ) {
return dirtyText.replace( /\s/g, '-' );
}
<?php
/**
* File used for displaying all single posts and attachments.
*
* @author Edwin Velez (https://edwinvelez.net)
*
* @since 1.2
* @version 1.0
*/
function edwinvelez_enqueue_scripts() {
wp_enqueue_script( 'toc', get_stylesheet_directory_uri() . '/genesis-build-sidebar-toc.js', array(), '1.0', true );
}
add_action( 'wp_enqueue_scripts', 'edwinvelez_enqueue_scripts' );
/**
* Displays a customized sidebar.
*
* By default only a skeleton of what the table of contents will be is given. The skeleton is populated via JavaScript.
*
* @since 1.2
* @version 1.0
*/
function edwinvelez_do_sidebar() {
?>
<h3 class="sidebar-primary-toc-header">Table of Contents</h3>
<section id="sidebar-primary-toc" class="sidebar-primary-toc">
<ul id="sidebar-primary-toc-headings">
</ul>
</section>
<?php
}
remove_action( 'genesis_sidebar', 'genesis_do_sidebar' );
add_action( 'genesis_sidebar', 'edwinvelez_do_sidebar' );
genesis();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.