Update: Added a conditional to ensure that wp_pagenavi() runs once.

The Elemin theme has it’s own built-in page navigation after the posts. It’s attractive, but not quite as flexible as the WP-PageNavi plugin. With this plugin you can put a page counter, link to the start and end pages, etc. It’s a cool add-on and I’ve gotten comfortable using it on my WordPress blog.

Adding support for that plugin to Elemin can be done simply by creating an includes directory for the child theme, and copying the elemin/includes/pagination.php file into the child theme includes directory. You then modify the copy with the wp_pagenavi() code and due to the magic of get_template_part() the child theme will pick that up.

Modifying a copy of a parent theme file isn’t too bad and that file is very small. But that’s not a very interesting solution. What’s more fun is to add support via hooking into the loop.

I’ve made many modifications to my child theme and not once have I had to copy and/or modify one of the parent theme files. For me, that’s the whole point of this exercise: creating a child theme that only uses functions.php and CSS.

So far using that method for this child theme I’ve been able to do the following:

  1. Add a random header image
  2. Made some CSS changes including a page background
  3. Added a fix for Internet Explorer 8 issues
  4. Created a front page view that shows the full content and then the excerpts and without using a front-page.php template

I’m having a great time doing it too. WordPress is very extensible and I’m picking up more and more PHP knowledge as a result of playing with my WordPress blog.

Here’s how I added support for WP-PageNavi to the Elemin theme.

1. Update the child theme’s functions.php file

The page navigation comes after all the posts so there are two actions I’m interested in. Those actions are called loop_start and loop_end. Neither is well documented in the WordPress Codex (it’s open to editing by anyone), but looking at other add_action() examples it’s not that hard to figure out.

A WordPress loop can happen at many different times in a WordPress blog. A plugin can create it own loops, the page slider does it, etc.

There is only one loop I want to play with and that’s the loop that happens right after the wp_head completes. To test that I check if the action wp_enqueue_scripts has completed. That action only completes in wp_head once so it’s a good test. I could have tested for wp_head but I forget why I chose that action instead.

If it did complete we’re after the wp_head so increment a counter. I implemented that check and counter using this code.

// Start the loop counter after wp_head
add_action( 'loop_start' , 'mh_main_loop_test' );

function mh_main_loop_test( $query ) {
global $mh_loop_count, $mh_pagenavi_done;
   if ( ( did_action( 'wp_enqueue_scripts' ) == 1 ) and !$mh_pagenavi_done ) {
      $mh_loop_count++;
      echo '<!-- loop counter = ' . $mh_loop_count . ' -->';
   }
}

At end of the loop, another action will be called. The loop counter is checked to see if it’s the first loop and only the first loop after wp_head. If it is, output the wp_pagenavi() and then decrease the counter. There is a check to make sure that the function wp_pagenavi exists so that PHP does not toss any errors.

// Display wp_pagenavi() at the end of the first loop only
add_action( 'loop_end' , 'mh_insert_after_posts' );

function mh_insert_after_posts( $query ) {
   global $mh_loop_count, $mh_pagenavi_done;
   $mh_after_head = did_action( 'wp_enqueue_scripts' );
   if ( $mh_after_head == 1 ) {
      if ( $mh_loop_count == 1 and function_exists( 'wp_pagenavi' )  and !$mh_pagenavi_done ) {
         echo '<!-- /loop counter = ' . $mh_loop_count . ' -->';
         wp_pagenavi();
         $mh_pagenavi_done = true;
      }
      // Done, so decrease the loop counter
      $mh_loop_count = $mh_loop_count - 1;
   }
}

Each time the loop starts the counter goes up, when the loop ends it decreases. I only want the wp_pagenavi() to run once and only at the end of the first loop. I output the counter as an HTML comment to confirm that everything is firing correctly.

2. Configure WP-PageNavi to use your CSS

Install the plugin and set the options as you see fit. Make sure you enable “Use pagenavi-css.css” because the default styling will look unattractive and the Elemin styling is pretty good.

I’ve create a file called pagenavi-css.css in the child theme and put in your CSS. I’ve copied the CSS from the Elemin child theme for the class pagenav. Except for some minor touches, the wp-pagenavi CSS class is identical to the pagenav class.

/* Hide the old pagenav */
.pagenav {
	display: none;
}
/* dupplicate the styling for WP-PageNavi */
.wp-pagenavi {
        clear: both;
        padding-bottom: 20px;
        text-align: right;
        margin: -30px 20px 0 20px;
}
.wp-pagenavi a, .wp-pagenavi span {
        min-width: 24px;
        min-height: 20px;
        line-height: 100%;
        text-decoration: none;
        text-align: center;
        margin: 0 3px;
        padding: 4px 0 0;
        vertical-align: middle;
        display: inline-block;
        zoom:1;
        *display:inline;
        -webkit-border-radius: 10em;
        -moz-border-radius: 10em;
        border-radius: 10em;
}
.wp-pagenavi a {
        background: #000;
        color: #fff;
        text-decoration: none;
}
.wp-pagenavi a:hover {
        background-color: #333;
        text-decoration: none;
}
.wp-pagenavi .current {
        color: #666;
        text-decoration: none;
}

There is one difference though. I’m using CSS to hide the default Elemin page navigation on the bottom. Yes, that means the old HTML is also being sent with the web page. But unless you look at the HTML source code you’ll never even know it’s there.

This CSS only gets used if the WP-PageNavi plugin is activated and if the pagenavi-css.css option is selected. Just by deactivating the plugin, the old page navigation is restored.

3. How about making this a plugin?

These functions and add_actions can be made into a plugin easily enough just by copying the code into a file in the wp-content/plugins directory. Call it elemin-wp-pagenavi.php.

At the top of that file put these lines

<?php
/*
Plugin Name: Add WP-PageNavi support to Elemin
*/

Then copy the code above right after that. You will still need to copy the pagenavi-css.css file to the elemin directory or the CSS will not get picked up.

Using this as a plugin will accomplish the same thing and avoid creating a child theme.

But if you are looking to making changes to the a theme then creating a child theme remains an easy thing to do. And I’ve been able to do this while avoiding modifying any copies of parent theme files.