While creating a new theme for this site, I added some CSS styling around the page/post navigation links.
For example, in my index.php
page, I have the following HTML/WordPress code:
<div class='navigation'>
<span class='older'><?php next_posts_link('« Older Entries') ?></span>
<span class='newer'><?php previous_posts_link('Newer Entries »') ?></span>
</div>
And the following CSS code:
.navigation {font-size:.7em; background:#353535; height:16px; margin:0 -16px 8px -16px; padding:8px 6px 0px;}
.navigation span {margin-top:-4px;}
.navigation .older {float:left;}
.navigation .newer {float:right;}
Everything looked great, until I brought up a page that did not have a previous or next link. The styled navigation div was still there, but there was nothing in it. So, I set out to conditionally display the navigation div if either a previous or next link existed.
WordPress gives you two different sets of functions to display page/post navigation links:
To display the previous and next page links (where the “next” page is the older entries or page n+1 and the “previous” page is the newer entries or page n-1): next_posts_link and previous_posts_link.
Note: It looks like the suggested function to call for these links is posts_nav_link, but it just calls next_posts_link and previous_posts_link internally, so I’ll just stick to calling them directly.
To display the previous and next post links (where the “next” post is a newer post entry and “previous” is an older post entry): next_post_link and previous_post_link.
So, I needed a way to capture the value of the next and previous links and then only display the navigation div if either contained a value. However, the WordPress functions mentioned above echo
the link HTML when called, making it impossible to add conditions around them.
A helpful person on the WordPress forums pointed out that a plugin would be overkill for solving this problem, so I created a functions.php file to my theme with two new functions and 4 overridden functions:
Note: I’ve posted a alternative solution.
<?php
/**
* New function that will display the navigation only if a previous or next page exists
* Hint: For pages, next == older and previous == newer
*/
function posts_navigation($next_label='« Older Entries', $previous_label='Newer Entries »', $max_page=0) {
$older = theme_next_posts_link($next_label);
$newer = theme_previous_posts_link($previous_label);
if(strlen($older) > 0 || strlen($newer) > 0) {
echo "<div class='navigation'>";
echo "<span class='older'>".$older."</span>";
echo "<span class='newer'>".$newer."</span>";
echo "</div>";
}
}
/**
* New function that will display the navigation only if a previous or next entry exists
* Hint: For entries, next == newer and previous == older
*/
function post_navigation($format='%link', $next_link='%title »', $previous_link='« %title', $in_same_cat = false, $excluded_categories = '') {
$older = theme_previous_post_link($format, $previous_link);
$newer = theme_next_post_link($format, $next_link);
if(strlen($older) > 0 || strlen($newer) > 0) {
echo "<div class='navigation'>";
echo "<span class='older'>".$older."</span>";
echo "<span class='newer'>".$newer."</span>";
echo "</div>";
}
}
/**
* Overrides the WordPress next_posts() function in link-template.php
* Modification: Changed echo to return
*/
function theme_next_posts($max_page = 0) {
return clean_url(get_next_posts_page_link($max_page));
}
/**
* Overrides the WordPress next_posts_link() function in link-template.php
* Modification:
* - Removed echo's
* - Added a $next_posts_link variable
* - Calls overridden next_posts() function, theme_next_posts()
* - Returns the $next_posts_link value
*/
function theme_next_posts_link($label='Next Page »', $max_page=0) {
global $paged, $wpdb, $wp_query;
$next_posts_link = '';
if ( !$max_page ) {
$max_page = $wp_query->max_num_pages;
}
if ( !$paged )
$paged = 1;
$nextpage = intval($paged) + 1;
if ( (! is_single()) && (empty($paged) || $nextpage <= $max_page) ) {
$next_posts_link .= '<a href="';
$next_posts_link .= theme_next_posts($max_page);
$next_posts_link .= '">'. preg_replace('/&([^#])(?![a-z]{1,8};)/', '&$1', $label) .'</a>';
}
return $next_posts_link;
}
/**
* Overrides the WordPress previous_posts() function in link-template.php
* Modification: Changed echo to return
*/
function theme_previous_posts() {
return clean_url(get_previous_posts_page_link());
}
/**
* Overrides the WordPress previous_posts_link() function in link-template.php
* Modification:
* - Removed echo's
* - Added a $previous_posts_link variable
* - Calls overridden previous_posts() function, theme_previous_posts()
* - Returns the $previous_posts_link value
*/
function theme_previous_posts_link($label='« Previous Page') {
global $paged;
$previous_posts_link = '';
if ( (!is_single()) && ($paged > 1) ) {
$previous_posts_link .= '<a href="';
$previous_posts_link .= theme_previous_posts();
$previous_posts_link .= '">'. preg_replace('/&([^#])(?![a-z]{1,8};)/', '&$1', $label) .'</a>';
}
return $previous_posts_link;
}
/**
* Overrides the WordPress previous_post_link() function in link-template.php
* Modification: Changed echo to return
*/
function theme_previous_post_link($format='« %link', $link='%title', $in_same_cat = false, $excluded_categories = '') {
if ( is_attachment() )
$post = & get_post($GLOBALS['post']->post_parent);
else
$post = get_previous_post($in_same_cat, $excluded_categories);
if ( !$post )
return;
$title = $post->post_title;
if ( empty($post->post_title) )
$title = __('Previous Post');
$title = apply_filters('the_title', $title, $post);
$string = '<a href="'.get_permalink($post->ID).'">';
$link = str_replace('%title', $title, $link);
$link = $pre . $string . $link . '</a>';
$format = str_replace('%link', $link, $format);
return $format;
}
/**
* Overrides the WordPress next_post_link() function in link-template.php
* Modification: Changed echo to return
*/
function theme_next_post_link($format='%link »', $link='%title', $in_same_cat = false, $excluded_categories = '') {
$post = get_next_post($in_same_cat, $excluded_categories);
if ( !$post )
return;
$title = $post->post_title;
if ( empty($post->post_title) )
$title = __('Next Post');
$title = apply_filters('the_title', $title, $post);
$string = '<a href="'.get_permalink($post->ID).'">';
$link = str_replace('%title', $title, $link);
$link = $string . $link . '</a>';
$format = str_replace('%link', $link, $format);
return $format;
}
?>
And now, I have conditional page/post navigation links for my theme!
Hi. I think there are two bugs here… I believe
$nextpage <= $max_page
should actually be
$nextpage < $max_page
And why is there a 1 at the end on the following line:
$nextpage = intval($paged) 1;
@Naif – this code was deprecated in favor of a different approach. However, you did find something that must have been garbled when posting:
$nextpage = intval($paged) 1;
should be:
$nextpage = intval($paged) + 1;
which makes
$nextpage <= $max_page
correct. I've updated the page and will put a note about this approach being replaced.Pingback: Infinite Scrolling: Adeus, links de navegação! | The Back-up Brain Weblog
Hi
I would like to use this function, or a variant of it but i cant get it working, basically i am using previous_post_link() as follows:
$img = "<img src=\"/image/galleries/" . $catnicename . "/" . $image ."\" alt=\"" . get_the_title() . "\" />";
if (previous_post_link('%link', $img, TRUE) == Null) {
echo $img;
} else {
previous_post_link('%link', $img, TRUE);
}
which works great inless there is a previous_post_link in which case it prints the link with the $img variable inbetween the >a href tags (which is what i want, and then the $img again.
I am thinking the solution is in your code here somewhere but i cant find it, could you help me out?
David
@David – Have you checked out the updated version of this concept?