Automatic Table of Contents Sticky Magellan Menu for WordPress Posts

Magellan Menu

See that sweet Magellan menu over on the right sidebar (if you’re not viewing the AMP version of this page)? →

Pretty cool right?

  • It acts as a nice table of contents for the post (and it’s 100% automatic!).
  • You can click the links to smooth scroll down to that section.
  • As you scroll, the visible section is highlighted.
  • It’s also inside of an awesome Theia Sticky Sidebar.

I’ll show you how to implement it into your own WordPress site.

What is a Magellan Menu?

Magellan is a fixed position menu that scrolls to the related anchor on click and follows you as you scroll, highlighting the active menu item.  It is a component that comes with the Foundation front-end framework (one of the most popular front-end website frameworks, competing with Bootstrap).

The same functionality could easily be translated to use ScrollSpy for Bootstrap.

How to Implement the Magellan Menu Functions and Shortcode

You should be able to drop the below code into your theme’s functions.php file.  It has all of the functions used to…

  • Get the text of all your post’s h2 tags.
  • Create a slug out of those h2 tags’ content.
  • Generate the Magellan menu.
  • Manipulate the post content to insert Magellan target slugs into the h2 tags.
  • Set up a simple little shortcode so you can put the Magellan menu wherever you want.
<?php

// Magellan Shortcode
add_shortcode( 'magellan', 'magellan_shortcode' );
function magellan_shortcode( $atts ) {
    if(is_admin()) return;
    $tag = 'h2';
    $html = get_the_content();
    $items = getTextBetweenTags( $tag, $html );
    return create_magellan($items);
}

/**
 * Magellan Functions
 */
function getTextBetweenTags($tag, $html, $strict=0) {
    // set error level
    $internalErrors = libxml_use_internal_errors(true);
    $dom = new domDocument;
    if($strict==1) {
        $dom->loadXML($html);
    } else {
        $dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
    }
    $dom->preserveWhiteSpace = false;
    $content = $dom->getElementsByTagname($tag);
    // Restore error level
    libxml_use_internal_errors($internalErrors);
    $out = array();
    foreach ($content as $item) {
        $out[] = $item->nodeValue;
    }
    return $out;
}
function create_slug($string){
    $replacement = array(
        "'" => '',
        '&amp;' => '',
        '&#8217;' => '',
    );
    foreach($replacement as $search => $replace) {
        $string = str_replace($search, $replace, $string);
    }
   $slug = preg_replace('/[^A-Za-z0-9-]+/', '-', strtolower( trim( $string ) ) );
   return $slug;
}
function create_magellan($items){
    $output .= '<ul class="magellan" data-magellan data-options="animationEasing:swing; animationDuration:750" data-offset="80">' . PHP_EOL;
    foreach( $items as $item ) {
        $output .= '<li><a href="#' . create_slug( $item ) . '" class="magellan-link">' . $item . '</a></li>';
    }
    $output .= '</ul>' . PHP_EOL;
    add_filter('the_content', 'magellan_content_formatter');
    return $output;
}
function magellan_content_formatter($content) {
    $new_content = '';
    $tag = 'h2';
    $pattern_full = '{(<' . $tag . '>.*?</' . $tag . '>)}is';
    $pattern_contents = '{<' . $tag . '>(.*?)</' . $tag . '>}is';
   $pieces = preg_split($pattern_full, $content, -1, PREG_SPLIT_DELIM_CAPTURE);
   // $new_content .= '<div class="sections">';
    foreach ($pieces as $piece) {
        if (preg_match($pattern_contents, $piece, $matches)) {
         $test = $matches[1];
         $testslug = create_slug($test);
            $new_content .= '<'.$tag.' id="'.$testslug.'" data-magellan-target="'.$testslug.'">'.$test.'</'.$tag.'>'.PHP_EOL;
        } else {
            $new_content .= wptexturize(wpautop($piece));
        }
    }
   // $new_content .= '</div>';
    return $new_content;
}
/**
 * End of Magellan Functions
 */

How to Place the Magellan Shortcode

Once you have the above code in place, placing the Magellan menu is as simple as typing the magellan shortcode in a sidebar widget.  Like this…

How to Make the Magellan Menu Sticky

There are lots of ways to make the Magellan Menu (or the widget area) sticky, but since the content of this menu is dynamic and could potentially be very long and not fit on the screen, I suggest using the Theia Sticky Sidebar.

How to Add a Scrolling Sticky Sidebar to WordPress

Comments or Question?

Let me know what you think.  Also, if you’re having issues getting yours to work properly, let me know where you’re stuck.  I’m happy to help.

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments