A better way to do this using Custom Pagers module is detailed in the Image module documentation: http://drupal.org/node/709462

description

The following adds a custom next_prev function to your theme template.php file that allows you to insert NEXT | PREVIOUS type links in your layout.tpl.php files. Where layout might be node.tpl.php, node-image.tpl.php etc.

In the illustrative example snippet below, a simple NEXT | PREVIOUS link is inserted into a custom node-image.tpl.php file linking to the next and previous image within that gallery (taxonomy term).

step 1 of 2

Add the custom next_prev function to your template.php file.

  1. In a text editor like notepad.exe or equivalent, create/edit a template.php file and paste the following snippet
  2. Save your new/edited template.php file and upload it to your active theme folder

function next_prev for Drupal 5

<?php
 function next_prev($current_nid, $type, $button_type, $label, $class) {
   $tid = db_result(db_query(db_rewrite_sql("SELECT tid FROM {term_node} WHERE nid = $current_nid;")));
   if (empty($tid)){ //validate that the image 'does' have a tid
    return '';
   }

   switch ($button_type) {
     case 'next':
       $sort= 'ASC';
       $case = '> ';
       break;
     case 'prev':
       $sort = 'DESC';
       $case = '< ';
       break;
     case 'parent':
       $name = db_result(db_query(db_rewrite_sql("SELECT name FROM {term_data} WHERE tid = $tid;")));
       return l($label.$name, "$type/tid/$tid", array('title' => $name, 'class' => $class));
       break;
     case 'last':
       $sql  = "SELECT n.nid, n.title FROM node n INNER JOIN term_node t ON n.nid = t.nid";
       $sql .= " INNER JOIN term_data r ON t.tid = r.tid WHERE n.type = '". $type ."'";
       $sql .= " AND r.tid = $tid AND n.status = 1 ORDER BY nid ASC LIMIT 0 , 1";
       $result = db_fetch_array(db_query(db_rewrite_sql($sql)));
       return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
       break;
     case 'first':
       $sql  = "SELECT n.nid, n.title FROM node n INNER JOIN term_node t ON n.nid = t.nid";
       $sql .= " INNER JOIN term_data r ON t.tid = r.tid WHERE n.type = '" .$type. "'";
       $sql .= " AND r.tid = $tid AND n.status = 1 ORDER BY nid DESC LIMIT 0 , 1";
       $result = db_fetch_array(db_query(db_rewrite_sql($sql)));
       return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
       break;
     default:
       return NULL;
       break;
   }
   $sql = "SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid ";
   $sql .= "INNER JOIN {term_data} r ON t.tid = r.tid WHERE n.type = '". $type ."' AND n.nid ". $case;
   $sql .= $current_nid ." AND r.tid = ". $tid ." AND n.status = 1 ORDER BY nid ". $sort;
   $result = db_fetch_array(db_query(db_rewrite_sql($sql)));
   if (!$result) {
     return NULL;
   } else {
     return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
   }
}
?>

function next_prev for Drupal 6

<?php
function next_prev($current_nid, $type, $button_type, $label, $class) {
  $tid = db_result(db_query(db_rewrite_sql("SELECT tid FROM {term_node} WHERE nid = %d"), $current_nid));
  if (empty($tid)){ //validate that the node 'does' have a tid
    return;
  }

  switch ($button_type) {
    case 'next':
      $sort= 'ASC';
      $case = '> ';
      break;
    case 'prev':
      $sort = 'DESC';
      $case = '< ';
      break;
    case 'parent':
      $name = db_result(db_query(db_rewrite_sql("SELECT name FROM {term_data} WHERE tid = %d"), $tid));
      return l($label.$name, "taxonomy/term/$tid", array('title' => $name, 'class' => $class));
    case 'last':
      $sql  = "SELECT n.nid, n.title FROM node n INNER JOIN term_node tn ON n.nid = tn.nid";
      $sql .= " INNER JOIN term_data td ON tn.tid = td.tid WHERE n.type = '%s'";
      $sql .= " AND td.tid = %d AND n.status = 1 ORDER BY nid ASC LIMIT 1";
      $result = db_fetch_array(db_query(db_rewrite_sql($sql), $type, $tid));
      return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
    case 'first':
      $sql  = "SELECT n.nid, n.title FROM node n INNER JOIN term_node tn ON n.nid = tn.nid";
      $sql .= " INNER JOIN term_data td ON tn.tid = td.tid WHERE n.type = '%s'";
      $sql .= " AND td.tid = %s AND n.status = 1 ORDER BY nid DESC LIMIT 1";
      $result = db_fetch_array(db_query(db_rewrite_sql($sql), $type, $tid));
      return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
    default:
      return;
  }
  $sql = "SELECT n.nid, n.title FROM {node} n 
                         INNER JOIN {term_node} tn ON n.nid = tn.nid 
                         INNER JOIN {term_data} td ON tn.tid = td.tid 
                              WHERE n.type = '%s' AND 
                                    n.nid " . $case . "%d AND 
                                    td.tid = %d AND 
                                    n.status = 1 
                           ORDER BY nid ". $sort . " LIMIT 1";
  $result = db_fetch_array(db_query(db_rewrite_sql($sql), $type, $current_nid, $tid));
  if (!$result) {
    return;
  } else {
    return l($label, 'node/'. $result['nid'], array('attributes'=>array('class'=>$class, 'title'=>$result['title']), 'html'=>TRUE));
  }
}
?>

step 2 of 2

Insert this snippet in your custom layout.tpl.php file and edit the $node->type to suit. This example snippet is intended for a custom node-image.tpl.php file. It inserts a link to the NEXT and PREVIOUS image within that image gallery (taxonomy term).

<?php 
  if ($terms && arg(0) == 'node' && is_null(arg(2))) {
      $next = next_prev($node->nid, 'image', 'next', 'next>', 'link'); // replace 'test' with a valid class for the link
      $previous = next_prev($node->nid, 'image', 'prev', '<previous', 'link');
      $last = next_prev($node->nid, 'image', 'last', 'last>>', 'link');
      $first = next_prev($node->nid, 'image', 'first', '<<first', 'link');
      $gallery = next_prev($node->nid, 'image', 'parent', '', 'link');
      print '<p><center>';
      if ($previous){ print $first .'&nbsp;&nbsp;'. $previous;}
      print '&nbsp;&nbsp;['. $gallery .']&nbsp;&nbsp;';
      if ($next){ print $next .'&nbsp;&nbsp;' .$last;}
      print '</center></p>';
    }
?>

notes

  • once added to your template.php file, the next_prev function maybe called from any custom layout.tpl.php file.
  • Please add a comment/child page with examples of using the custom next_prev function in your layout.tpl.php files.

Comments

bdimaggio’s picture

This is a super-useful piece of code and was working fine for me until I installed I18n, at which point I started getting a bunch of SQL errors like the following:
user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ';)' at line 1 query: SELECT tid FROM term_node LEFT JOIN i18n_node i18n ON n.nid = i18n.nid WHERE (i18n.language ='en' OR i18n.language ='' OR i18n.language IS NULL) AND ( nid = 125;) in /home/digitao0/public_html/ecologic/includes/database.mysql.inc on line 172.

I fooled around with this a bit and discovered that some small changes to the SQL (adding brackets to all the tables that get referred to, removing the semicolon from the first SQL statement, adding a LEFT JOIN to bring the node table into that statement) fixed the problem. Here's what works for me:

  
function next_prev($current_nid, $type, $button_type, $label, $class) {
   $tid = db_result(db_query(db_rewrite_sql("SELECT tn.tid FROM {term_node} tn LEFT JOIN {node} n ON tn.nid=n.nid WHERE tn.nid = $current_nid")));
   if (empty($tid)){ //validate that the image 'does' have a tid
    return '';
   }
   
   switch ($button_type) {
     case 'next':
       $sort= 'DESC';
       $case = '< ';
       break;
     case 'prev':
       $sort = 'ASC';
       $case = '> ';
       break;
     case 'parent':
       // $name = db_result(db_query(db_rewrite_sql("SELECT name FROM {term_data} WHERE tid = $tid;")));
       return l($label, "$type/tid/$tid", array('title' => $label, 'class' => $class));
       break;
     case 'last':
       $sql  = "SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid";
       $sql .= " INNER JOIN {term_data} r ON t.tid = r.tid WHERE n.type = '". $type ."'";
       $sql .= " AND r.tid = $tid AND n.status = 1 ORDER BY nid ASC LIMIT 0 , 1";
       $result = db_fetch_array(db_query(db_rewrite_sql($sql)));
       return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
       break;
     case 'first':
       $sql  = "SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid";
       $sql .= " INNER JOIN {term_data} r ON t.tid = r.tid WHERE n.type = '" .$type. "'";
       $sql .= " AND r.tid = $tid AND n.status = 1 ORDER BY nid DESC LIMIT 0 , 1";
       $result = db_fetch_array(db_query(db_rewrite_sql($sql)));
       return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
       break;
     default:
       return NULL;
       break;
   }
   $sql = "SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid ";
   $sql .= "INNER JOIN {term_data} r ON t.tid = r.tid WHERE n.type = '". $type ."' AND n.nid ". $case;
   $sql .= $current_nid ." AND r.tid = ". $tid ." AND n.status = 1 ORDER BY nid ". $sort;
   $result = db_fetch_array(db_query(db_rewrite_sql($sql)));
   if (!$result) {
     return NULL;
     return l($label.$name, "$type/tid/$tid", array('title' => $name, 'class' => $class));
   } else {
     return l($label, 'node/'. $result['nid'], array('title' => $result['title'], 'class' => $class));
   }
}
giuvax’s picture

with this code:

     case 'parent':
       // $name = db_result(db_query(db_rewrite_sql("SELECT name FROM {term_data} WHERE tid = $tid;")));
       return l($label, "$type/tid/$tid", array('title' => $label, 'class' => $class));
       break;

You lose the name of the parent gallery. The right code are the lines of the original version of the snippet. I solved it.

Bye! and thanks

Saigon... shit; I'm still only in Saigon.

giuvax’s picture

Hi,
I got an error on this snippet until I found the problem, with italian community help.
Drupal got an sql error because of the missing {} in the first two groups of sql queries.
You see, on the case 'default' the tables name are between {} and Drupal finds them.
My Drupal didn't find the tables in the case 'last' and 'first', I had to put the table names between {} and with this correction finally it's working.

Bye!

Saigon... shit; I'm still only in Saigon.

camb416’s picture

Thank you so much for these extremely helpful snippets!

I do have a question however... these snippets sort by node ID. I am entering a back catalog of content, so the IDs are out of order. Can someone assist me in changing the SQL lines so that the nodes returned are sorted by Authored Date?

Any help would be tremendously appreciated!

deelite’s picture

And i am looking for a solution for sorting it by a cck-field.

I have one "sort_order" to change the sort-order manual. And now i want to sort the prev/next by this field.

can anyone help me?

Or did you find a solution, camb?

clau_bolson’s picture

I am extremely interested in this! Image gallery without "next" and "previous" in each photo is extremely tiresome and will blow away any visitor.

deelite’s picture

I was searching for a solution exactly like that for about 1 week. Thank you so much!

The "

" Phrases i was replacing with an Only local images are allowed. and it works perfect. Now i need to replace the link to the gallery and i don't know how? When i replace the "'parent'" - there was nothing to show. No textlink and no image. When i replace the "$gallery" - there was showing the image but without a link around that. Can anyone help me to get the gallery-link replacing with an image? Thank you for reading that.
deelite’s picture

I got it working with this Code in node.tpl.php:

	  if ($terms && arg(0) == 'node' && is_null(arg(2))) {
			$next = next_prev($node->nid, 'project_cd', 'next', '', 'link_next');
			$previous = next_prev($node->nid, 'project_cd', 'prev', '', 'link_prev');
			if ($previous){ print $previous; }
			print ('<a href="path_to_gallery" title="title" class="link_gallery"></a>');
			if ($next){ print $next; }
		 }
	
borazslo’s picture

And in D7?

kumkum29’s picture

Is there a version for drupal 7?

remaye’s picture

+1

bijibiji’s picture

Drypal 7 function

function taxonomy_select_nodes_from_nid($tid, $nid, $direction = 'next', $limit = 1) {
    if (!variable_get('taxonomy_maintain_index_table', TRUE)) {
        return array();
    }
    $query = db_select('taxonomy_index', 't');
    $query->addTag('node_access');
    $query->condition('tid', $tid);
    $query->condition('nid', $nid, $direction == 'next' ? '>' : '<');

    if ($limit !== FALSE) {
        $query->range(0, $limit);
    }

    $query->addField('t', 'nid');
    $query->addField('t', 'tid');
    $query->orderBy('t.nid', $direction == 'next' ? 'ASC' : 'DESC');

    return $query->execute()->fetchCol();
}

Using

    $next_node = taxonomy_select_nodes_from_nid($term->tid, $node->nid, 'next');
    $prev_node = taxonomy_select_nodes_from_nid($term->tid, $node->nid, 'prev');
edunn’s picture

(for Drupal 6) I've got this working, but It's not pulling from the correct taxonomy. Anyone know how to pick the taxonomy vocabulary it uses?

Thanks so much,
Evan

Dimm’s picture

D7 variant
template.php

function taxonomy_select_nodes_from_nid($tid, $nid, $direction = 'next', $limit = 1) {
    if (!variable_get('taxonomy_maintain_index_table', TRUE)) {
        return array();
    }
    $query = db_select('taxonomy_index', 't');
    $query->addTag('node_access');
    $query->condition('tid', $tid);
    $query->condition('nid', $nid, $direction == 'next' ? '>' : '<');

    if ($limit !== FALSE) {
        $query->range(0, $limit);
    }

    $query->addField('t', 'nid');
    $query->addField('t', 'tid');
    $query->orderBy('t.nid', $direction == 'next' ? 'ASC' : 'DESC');

    return $query->execute()->fetchCol();
}

node.tpl.php

<div>
  <?php  
    $prev_node_nid_arr = taxonomy_select_nodes_from_nid($node->field_tags['und'][0]['tid'], $node->nid, 'prev');
	if(sizeof($prev_node_nid_arr)){
		$prev_node=node_load($prev_node_nid_arr[0]);
		print '<a href="/node/'. $prev_node->nid.'"> << '.$prev_node->title.' << </a>';	
	}

    $next_node_nid_arr = taxonomy_select_nodes_from_nid($node->field_tags['und'][0]['tid'], $node->nid, 'next');
	if(sizeof($next_node_nid_arr)){
		$next_node=node_load($next_node_nid_arr[0]);
		print '&nbsp;&nbsp;&nbsp;&nbsp;<a href="/node/'. $next_node->nid.'"> >> '.$next_node->title.' >> </a>';	
	}
?>
</div>
Ruriko’s picture

Doesn't this overload the database? especially when you have over 1000 users viewing at the same time (caching only helps only a little)

floydm’s picture

Very helpful and exactly what I needed.

I needed this for a couple of projects with a few variations, so I turned this snippet into a little module. You can change the tpl and select whether the labels say "Next" and "Previous" or display the next and previous node titles. Please feel free to take it and put it to use!

-Floyd

Dajia Dim’s picture

template.php

function to get current language:


<?php
function lang_base_path() {
  global $language_content; 
  $lang = $language_content->language; 
  return base_path().$lang."/";
}
?>

the above function for next/prev links


<?php
function taxonomy_select_nodes_from_nid($tid, $nid, $direction = 'next', $limit = 1) {
    if (!variable_get('taxonomy_maintain_index_table', TRUE)) {
        return array();
    }
    $query = db_select('taxonomy_index', 't');
    $query->addTag('node_access');
    $query->condition('tid', $tid);
    $query->condition('nid', $nid, $direction == 'next' ? '>' : '<');
    if ($limit !== FALSE) {
        $query->range(0, $limit);
    }
    $query->addField('t', 'nid');
    $query->addField('t', 'tid');
    $query->orderBy('t.nid', $direction == 'next' ? 'ASC' : 'DESC');
    return $query->execute()->fetchCol();
}
?>

node.tpl.php

        <div>
            <?php
            $prev_node_nid_arr = taxonomy_select_nodes_from_nid($node->field_tags['und'][0]['tid'], $node->nid, 'prev');
            if(sizeof($prev_node_nid_arr)){
                $prev_node=node_load($prev_node_nid_arr[0]);
                print '<a href=' . lang_base_path() .'node/'. $prev_node->nid.'&nbsp;&nbsp;&nbsp;&nbsp;> previous   </a>';
            }
            $next_node_nid_arr = taxonomy_select_nodes_from_nid($node->field_tags['und'][0]['tid'], $node->nid, 'next');
            if(sizeof($next_node_nid_arr)){
                $next_node=node_load($next_node_nid_arr[0]);
                print '&nbsp;&nbsp;&nbsp;&nbsp;<a href=' . lang_base_path() .'node/'. $next_node->nid.'>  next </a>';
            }
            ?>
        </div>