ThemeShaper Forums » Thematic

Table of contents on category archive pages

(12 posts)
  • Started 10 years ago by bijoor
  • Latest reply from bijoor
  • This topic is not resolved
  1. I want to create a table of contents at the top of every category archive page, which lists out the titles of posts listed, and with anchor links on each title.

    What is the simplest way to do this?

    I know I can hook in to the thematic_above_categoryloop to display the result, but do not know an easy way to:
    - create the table of contents list
    - insert anchors in the listed posts

    Posted 10 years ago #
  2. Hi bijoor

    I've used this TOC plugin with thematic before with good results. It automates the TOC and anchor creation... much easier than doing it manually.


    Posted 10 years ago #
  3. Thanks for the suggestion Gene, I'd thought of that one but to no avail :(
    It (and others similar to it) only create a TOC for headings in a single post / page

    What I want is a TOC for multiple posts pages - specifically for category archive pages.

    Have implemented a jquery solution for it... will post shortly

    Posted 10 years ago #
  4. Here is the jquery way to do it.

    I'd still like a non-JS solution, so that it can handle mobile browsers... but this is a way out for now...

    In functions.php:

    // add the script to generate the TOC
    function init_scripts() {
        wp_enqueue_script('jquery_cycle', get_bloginfo('stylesheet_directory').'/js/jquery.cycle.all.min.js',array('jquery'));
    	wp_enqueue_script('init_category_toc', get_bloginfo('stylesheet_directory').'/js/init_category_toc.js',array('jquery'));
    add_action('init', init_scripts);
    // add a container for the table of contents to category pages
    function my_category_toc() {
    	echo('<div id="category-toc"><h3>Articles in this category</h3></div>');
    add_action('thematic_above_categoryloop', 'my_category_toc', 0);

    And add a file init_category_toc.js in js folder in the theme with the following code:

    /* Initialize Category TOC
    jQuery(function( $ ){
    	$('.entry-title').each(function(i) {
    		$('#category-toc ul').append('
    <li><a href="#post-'+i+'">'+$(this).text()+'</a></li>
    	$('.entry-utility').append('<span class="meta-sep"> | </span><span class="top-link"><a href="#">Top</a></span>');

    Good enough for now, till someone helps me with a PHP solution :)

    Posted 10 years ago #
  5. Yeah client side maybe the best way to TOC a multiple post ( index or archive) page. This could be done with php by storing the loop output as a string and then filtering it.

    Tricky since most of thematic's functions echo; but this could be done in cooperation with the plugin I mentioned.

    Posted 10 years ago #
  6. I use this plugin a good bit so this has intrigued me. You could apply this same method to store and filter of the loop with some other plugin or function. This is a pretty good beginning.

    function remove_thm_cat_loop() {
    function child_cat_loop() {
    	// Store the loop in a string so it can be filtered
    	global $id, $post, $authordata;
    	while (have_posts()) : the_post();
    		// recreating the thematic functions that build the loop without echoing
    		$cat_div_open  = '<div id="post-' . get_the_ID() . '" class="' . thematic_post_class(false) . '">';
    		// entry header
    		$cat_header = '<h2 class="entry-title"><a href="'.get_permalink().'" title="';
    		$cat_header .=  __('Permalink to ', 'thematic') . the_title_attribute('echo=0');
    		$cat_header .=  '" rel="bookmark">';
    		$cat_header .=  get_the_title();
    		$cat_header .=  "</a></h2>\n";
    		// entry postmeta
    		$cat_postmeta  = '<div class="entry-meta">';
    		$cat_postmeta .= '<span class="meta-prep meta-prep-author">' . __('By ', 'thematic') . '</span>';
    		$cat_postmeta .= '<span class="author vcard">'. '<a class="url fn n" href="';
    		$cat_postmeta .= get_author_link(false, $authordata->ID, $authordata->user_nicename);
    		$cat_postmeta .= '" title="' . __('View all posts by ', 'thematic') . get_the_author() . '">';
    		$cat_postmeta .= get_the_author();
    		$cat_postmeta .= '</a></span><span class="meta-sep meta-sep-entry-date"> | </span>';
    		$cat_postmeta .= '<span class="meta-prep meta-prep-entry-date">' . __('Published: ', 'thematic') . '</span>';
    		$cat_postmeta .= '<span class="entry-date"><abbr class="published" title="';
    		$cat_postmeta .= get_the_time(thematic_time_title()) . '">';
    		$cat_postmeta .= get_the_time(thematic_time_display());
    		$cat_postmeta .= '</abbr></span>';
    		// edit link
    		if (current_user_can('edit_posts')) {
    	        $cat_postmeta .= ' <span class="meta-sep meta-sep-edit">|</span> ' . $posteditlink;
    			$cat_postmeta .= '<span class="edit"><a href="' . get_bloginfo('wpurl') . '/wp-admin/post.php?action=edit&amp;post=' . $id;
    			$cat_postmeta .= '" title="' . __('Edit post', 'thematic') .'">';
    			$cat_postmeta .= __('Edit', 'thematic') . '</a></span>';
    		$cat_postmeta .= '</div<!-- .entry-meta-->';
    		// entry content
    		// could be changed to get_the_excerpt()
    		$cat_content = '<div class="entry-content">'.get_the_content().'</div>';
    		// entry footer
    		$cat_footer  = '<div class="entry-utility">';
    		// cat links
    		// ?? not sure but cats meow not working to exclude current cat from list
    		if ( is_category() && $cats_meow = thematic_cats_meow(', ') ) { /* Returns categories other than the one queried */
           		$cat_footer .= __('Also posted in ', 'thematic') . $cats_meow;
           	 	$cat_footer .= '</span> <span class="meta-sep meta-sep-tag-links">|</span>';
        		} else {
            	$cat_footer .= __('Posted in ', 'thematic') . get_the_category_list(', ');
            	$cat_footer .= '</span> <span class="meta-sep meta-sep-tag-links">|</span>';
    		// comments
    		 if (comments_open()) {
    	        $postcommentnumber = get_comments_number();
    	     	if ($postcommentnumber > '1') {
    	            $cat_footer .= ' <span class="comments-link"><a href="' . get_permalink() . '#comments" title="' . __('Comment on ', 'thematic') . the_title_attribute('echo=0') . '">';
    	            $cat_footer .= get_comments_number() . __(' Comments', 'thematic') . '</a></span>';
    	        } elseif ($postcommentnumber == '1') {
    	            $cat_footer .= ' <span class="comments-link"><a href="' . get_permalink() . '#comments" title="' . __('Comment on ', 'thematic') . the_title_attribute('echo=0') . '">';
    	            $cat_footer .= get_comments_number() . __(' Comment', 'thematic') . '</a></span>';
    	        } elseif ($postcommentnumber == '0') {
    	            $cat_footer .= ' <span class="comments-link"><a href="' . get_permalink() . '#comments" title="' . __('Comment on ', 'thematic') . the_title_attribute('echo=0') . '">';
    	            $cat_footer .= __('Leave a comment', 'thematic') . '</a></span>';
    	    } else {
    	        $cat_footer .= ' <span class="comments-link comments-closed-link">' . __('Comments closed', 'thematic') .'</span>';
    		// edit link
    		if (current_user_can('edit_posts')) {
    	        $cat_footer .= ' <span class="meta-sep meta-sep-edit">|</span> ' . $posteditlink;
    			$cat_footer .= '<span class="edit"><a href="' . get_bloginfo('wpurl') . '/wp-admin/post.php?action=edit&amp;post=' . $id;
    			$cat_footer .= '" title="' . __('Edit post', 'thematic') .'">';
    			$cat_footer .= __('Edit', 'thematic') . '</a></span>';
    		$cat_footer .= "</div><!-- .entry-utility -->\n";
    		$cat_div_close = '</div><!-- .post -->';
    		// put it all together
    		$cat_entry = $cat_div_open . $cat_header . $cat_postmeta . $cat_content . $cat_footer . $cat_div_close;
    		// count and concatenate entries
    		if ($i=0)  {
    			$cat_loop = $cat_entry;
    			} else {
    			$cat_loop .= "\n". $cat_entry;
    	// Now that the loop is in a string
    	// Load the content from $cat_loop
    	$wptoc_contents = $cat_loop;
    	// Be sure the plugin functions you'll need are available
    	$wptoc_exists = function_exists('wptoc_toc') && function_exists('wptoc_as_ulist');
    	// If the plugin is available,
    	if($wptoc_exists) {
    	    // Extract the table of contents from your content
    	    $wptoc = wptoc_toc($wptoc_contents);
    	    // Generate the table of contents html for that content
    	    $wptoc_toc = wptoc_as_ulist($wptoc['toc']);
    	    // Replace our original content with the content plus named anchors
    	    // to allow linking to sections from the table of contents.
    	    $wptoc_contents = $wptoc['html-with-anchors'];
    		// To display the toc now you just:
    		echo $wptoc_toc;
    		// Keep your markup for the TOC in this conditional
    		// so if the plugin goes missing
    		// so will the TOC output
    	// To display the content of the file with named anchors added to allow linking from the toc you:
    	// Keeping this outside the conditional so content always shows
    	 echo $wptoc_contents;
    	// to do: preg_replace to insert a top anchor attached to TOC markup
    Posted 10 years ago #
  7. Hey Thanks for the code, Gene! I see the way now, but may choose to keep the client side solution for now in favor of the brevity of code :)

    Is there a way to retain the default category loop and merely hook into the entry title and entry footer? Then we could just add the anchor in the title and a top link in the footer, keeping the titles in a global array, then create the TOC from it. Would probably end up with fewer lines of code???

    Posted 10 years ago #
  8. Yeah, that example works best as an extension of that plugin. Typing out that code gives me respect for what goes into a thematic loop.

    WPow! I see a simpler way to do it. Run two loops.

    The first hooks into above_category_loop and rewind_posts at the end. This one builds a TOC.
    Instead of adding new anchors... Blam! Just use the post div id attribute as the anchor. That is easy to target in the TOC since thematic assigns it the post_id. No need to mess with thematic_category_loop since that is our second loop and it already has the id's we 're targeting. And we could filter the thematic_post_footer with is_category to add a top link to an element id attached to the TOC. No plugin no empty anchors. I think that will actually work. I'll skadiddle with it tomorrow :)

    Posted 10 years ago #
  9. I hereby define WPow as the moment one realizes that they just spent 45min doing something that could be done in 5.

    function cat_toc_loop() {
    	<ul id="cat-toc">
    	 <?php while (have_posts()) : the_post(); ?>
    		<li class="toc-item toc-item-<?php the_ID(); ?>">
    			<a href="#post-<?php the_ID(); ?>"><?php the_title(); ?></a>
    	 <?php endwhile; ?>
    	</ul><!-- .post -->
    add_action('thematic_above_categoryloop', 'cat_toc_loop');
    function  toc_bouy($meta) {
    	$replacement = "<span class=\"meta-sep meta-sep-toc\"> |</span><a href=\"#cat-toc\"> [&uarr;]</a>\n</div>";
    	$meta_bouy = str_replace( '</div>', $replacement, $meta ); //str_replace(mixed search, mixed replace, mixed subject [, int &count])
    	return $meta_bouy;
    // attaches bouy to post header	@css .entry-meta
    add_filter('thematic_postheader', 'toc_bouy');
    // attaches bouy to post footer @css .entry-utilty
    add_filter('thematic_postfooter', 'toc_bouy');

    Try that and let me know how it works for you.


    Posted 10 years ago #
  10. That's a neat solution, Gene!
    Thanks a lot... will use this approach...
    Just noticed you probably forgot to add the rewind_posts in the code... but that was a master stroke :-)

    Posted 10 years ago #
  11. I'm pretty sure I was wrong about needing rewind_posts. Since we're using the same query with the same count.

    Posted 10 years ago #
  12. Oh ok... will try it and see if it works. Not really clear about the way the loop works twice

    Posted 10 years ago #

RSS feed for this topic


You must log in to post.