Creating a clickable index from posts

I started creating a sort of E-book in WordPress and could not find a good plugin for creating a clickable index in the beginning. So I baked my own. I created a page template that shows all articles in a certain category. So first you need to have a page and some articles in a category. This solution uses the <h1> and <h2> tags for the index. You can add more levels, if you wish.

This solution uses a PHP library called Simple HTML DOM for parsing the HTML and jQuery for JavaScript

PHP

This goes into the page template

<div id="tw_index">
<?php 
require_once( 'simple_html_dom.php' );
//use the ID of the category you wish to show
$args = array( 'posts_per_page' : -1,'category' : 100,'orderby' : 'date', 'order' : 'ASC' );
$myposts = get_posts( $args );
$int = 1; //for numbering the main indexes

foreach ( $myposts as $post ) : setup_postdata( $post );
     //since the title is not in the content, it needs to be added and wrapped in a H1
     //and a SPAN since we do not want the numbering included later on
     $html = str_get_html("<h1><span>$int. " . get_the_title() . "</h1>" . $post->post_content . "</span></h1>); 
     foreach($html->find('h1,h2') as $h){
          echo $h->outertext; } 
          $int++; 
     endforeach;
?>

//And now the content
<div id="tw_content">

<?php foreach ( $myposts as $post ) : setup_postdata( $post ); ?>
      <h1><?php the_title(); ?></h1>
     <p><?php the_content(); ?></p>
<?php endforeach; 
wp_reset_postdata();?>

</div>

 

JavaScript

The code below is added to the footer or header (the proper way of adding it)

//read only the text, not the index number, for <h1>
jQuery("#tw_index h1 span").click(function(){tw_scrollTo('h1', jQuery(this).text());});
jQuery("#tw_index h2").click(function(){tw_scrollTo('h2', jQuery(this).text());});

function tw_scrollTo(el, elname){
     var nAttr = "#tw_content " + el + ":contains('" + elname +"')";
     jQuery('html, body').animate({//nicely animated ;-)
          scrollTop: jQuery(nAttr).offset().top -200
     }, 1000);
}

CSS

This goes to the styles.css so that the whole thing is more readable, also, since the clickable areas are not links, we need to change the cursor on hover and add a highlight.

div#tw_index h1{
     padding:0px;
     font-size:20px;
     margin:20px 0 6px 0;
     color:#428bca;
}

div#tw_index h2{
     padding:0px;
     font-size:16px;
     margin:0 0 6px 25px;
     color:#428bca;
}

div#tw_index h1:hover{
     color:#e24871;
     cursor:pointer;
}

div#tw_index h2:hover{
     color:#e24871;
     cursor:pointer;
}