Skip to main content
  • Home
  • Blog
  • Sandbox

Alvin Pascoe

Website Developer

Alvin Pascoe
Loading.....
  • Drupal 7 Dynamic Content Carousel - AJAX Improvements
    Drupal 7 Dynamic Content Carousel - AJAX Improvements
  • Drupal 7 Dynamic Content Carousel - Carousel Transitions
    Drupal 7 Dynamic Content Carousel - Carousel Transitions

Drupal 7 Dynamic Content Carousel - Dynamic Next and Previous Links

UPDATE: The custom module file created in this part of the tutorial are now available on GitHub: Dynamic Content Carousel - Dynamic Next and Previous Links.

17th April, 2015

This is part four of a five part series Drupal 7 Dynamic Content Carousel. If you haven't read part one yet, it may help to read it before moving forward - Part One - Introduction

In the previous part of the series, we completed a custom Drupal module which allows us to dynamically load node content based on a link. We were using a static link to test the AJAX functionality, however in the final carousel, we want that link to be generated dynamically (based on the available content and their publication dates). Let's look into this now.

Research

After looking around I found a few different solutions, I could either use a suitable module or create the setup manually. When given the choice, I usually opt for manual setup (if implementation is straightforward) since it gives me more control over the execution and cuts down on bloat. That being said, if there's a module that provides the exact functionality I'm looking for and it seems stable and light, I'll happily use it!

The manual option involves adding code to either template.php or creating a custom module. The implementation would search the database for the next/previous node of a certain content type based on the current node id (searches would be completed using the EntityFieldQuery API).

I was about to start creating a manual solution when I noticed something on the 'Previous/Next API' module page.

Although the previous and next nodes can be deduced with some SQL work, the queries to do so are very heavy on the database, and can bring a site to its knees. This module solves this problem by storing the previous/next node in a table so lookups are fast. Once the module is installed, it will build this index backwards via cron until all nodes have been indexed.

Previous/Next API Module

It mentioned using cron to create an index of monitored pages in order to increase efficiency. I'm all for increased efficiency!

On closer inspection, the module seemed to achieve exactly what I wanted and it seemed quite light, so I thought I'd play with it for a while and see what happened. What happened was it worked great!

Implementation

Step 1 - Download 'Previous/Next API' module

Download and enable the 'Previous/Next API' module or run the following drush command:

drush dl prev_next && drush en prev_next

Step 2 - Configure Settings

Navigate to the 'Previous/Next API' settings page at '/admin/config/system/prev_next'.

To monitor a specific content type, simply click the 'Include' checkbox. Since I want my articles sorted by publication date, I also changed the 'Indexing criteria' to 'Post date'.

Save these changes and re-index the site. For me, the 'Re-index' button wasn't working correctly but I triggered a re-indexing by forcing a cron run via '/admin/config/system/cron' or by using:

drush core-cron

You can check indexing progress via the 'Indexing Status' section on the module's settings page.

Step 3 - Create function using Previous/Next API

Now we've installed and configured the module, it's time to use it. First we'll create a function which makes use of the prev_next_nid() function supplied by the module and returns a link to either the next or the previous node (based on the configuration set in the previous step). The module's README.txt helpfully supplies a great example of just such a function!

I've borrowed heavily from their example and tweaked it to suit my situation. The function below can be placed in a custom module or your template.php file (update the function name appropriately with either <module name>_pn_node() or <theme>_pn_node() in line with Drupal best practice). I've created a new custom module 'Previous Next Node'.

/**
 * Prev Next Module utility function
 */
function previous_next_node_pn_node($node, $mode = 'n') {
  // If the Previous/Next API's helper function does
  // not exist, exit function.
  if (!function_exists('prev_next_nid')) {
    return NULL;
  }

  // Depending on the $mode, retrieve either the
  // previous or next NID.
  switch($mode) {
    case 'p':
      $n_nid = prev_next_nid($node->nid, 'prev');
      $link_text = 'previous';
      break;

    case 'n':
      $n_nid = prev_next_nid($node->nid, 'next');
      $link_text = 'next';
      break;

    default:
      return NULL;
  }

  // If we obtained a NID.
  if ($n_nid) {
    $n_node = node_load($n_nid);

    $options = array(
      'attributes' => array('class' => 'thumbnail'),
      'html'  => TRUE,
    );

    switch($n_node->type) {
      // For image nodes only.
      case 'image':
        // This is an image node, get the thumbnail
        $html = l(image_display($n_node, 'thumbnail'), "node/$n_nid", $options);
        $html .= l($link_text, "node/$n_nid", array('html' => TRUE));
        return $html;

      // For video nodes only.
      case 'video':
        foreach ($n_node->files as $fid => $file) {
          $html  = '<img src="' . base_path() . $file->filepath;
          $html .= '" alt="' . $n_node->title;
          $html .= '" title="' . $n_node->title;
          $html .= '" class="image image-thumbnail" />';
          $img_html = l($html, "node/$n_nid", $options);
          $text_html = l($link_text, "node/$n_nid", array('html' => TRUE));
          return $img_html . $text_html;
        }

      // For all other nodes.
      default:
        // Generate a non-ajax and ajax link, using the appropriate NID and link text.
        $prettyUrl = url('node/'.$n_nid);
        $text_html = l($link_text, "node/$n_nid", array('html' => TRUE, 'attributes' => array('class' => 'no-js')));
        $text_html .= l($link_text, "/blog/nojs/$n_nid", array('html' => TRUE, 'attributes' => array('class' => 'use-ajax', 'data-node' => $n_nid, 'data-url' => $prettyUrl)));
        return $text_html;
    }

  }
}

previous_next_node.module

I've left in the 'case: 'image:'' and 'case: 'video:'' sections to demonstrate other uses of this function, however we will not be using it in our example (so feel free to remove them).

If you followed along with the AJAX tutorials in this series, you'll remember that the static link we used for testing contained two 'data' attributes, 'data-url' for storing the aliased URL and 'data-node' for storing the node id. We also included a second, non-AJAX link.

In the default: case of the pn_node() function, I'm returning both links along with the classes and 'data' attributes used in our static test links.

Step 4 - Print Dynamic Links

I only wanted to print my Next/Previous blog article links inside 'Article' nodes. In order to do this, I created a new theme template file, node--article.tpl.php. The machine name of my Article content type is 'article', update this to match whatever content type you're using. Create this file inside your /sites/all/themes/<theme>/templates directory.

After copying the contents of your current theme's node.tpl.php into the new template file, add the following code after the main content
(remember to update the previous_next_node_pn_node() function name to match that which you created in your custom module or template.php):

<?php // Previous/Next API ?>
<ul class="js-ajax-loader js-carousel-pager">
  <li class="next"><?php print previous_next_node_pn_node($node, 'n'); ?></li>
  <li class="prev"><?php print previous_next_node_pn_node($node, 'p'); ?></li>
</ul>

<THEME>/templates/node--article.tpl.php

Now clear your cache.

I've added a couple of classes to the link list:

  • js-ajax-loaderis the selector used by the 'Ajax Content Loader' module.
  • js-carousel-pagerwill be used by the carousel we'll set up in the next part of this series.

Now test the new links at the bottom of your page...you should have 'Next' and 'Previous' links displaying on the site! When clicked, the appropriate content will dynamically load on the page. Almost feels a little too easy! Now we have the dynamic links, we can remove the static links we created previously.

In the next and final part of this series, we'll throw a carousel into the mix and use it to create transitions between page updates!

  • Drupal
  • Tutorial
  • Previous Article: Drupal 7 Dynamic Content Carousel - AJAX Improvements
    Previous Article: Drupal 7 Dynamic Content Carousel - AJAX Improvements
  • Next Article: Drupal 7 Dynamic Content Carousel - Carousel Transitions
    Next Article: Drupal 7 Dynamic Content Carousel - Carousel Transitions

Blog Archives

  • December 2019 (1)
  • November 2019 (1)
  • August 2019 (1)
  • May 2019 (1)
  • October 2018 (1)
  • February 2017 (2)
  • January 2017 (3)
  • November 2016 (1)
  • July 2016 (1)
  • January 2016 (1)
More...

Categories

  • Angular
  • CSS
  • Development Environment
  • Drupal
  • Git
  • JavaScript
  • Mac
  • Programming
  • React
  • Tutorial
  • Workflow
  • Home
  • Blog
  • Sandbox
  • Pattern Library
© 2026 Alvin Pascoe
hello{at}alvinpascoe{dot}com
Made by Me, Alvin Pascoe