Drupal 7 & 8 & 9: How to implement isotope and infinitescroll using Views only!

12 Dec.2014
drupal + view + isotope + infinitescroll

I will begin my story with the fact that Drupal already has greatly finished contrib modules to implement this functionality.

It's just not full list:

What makes these modules? That's right, they check for libraries and their version, they change the HTML output, they allow flexibility to change some settings in the admin section.

However, for some reason, you do not want to use two or three additional modules.

The reasons may be different. For example:

  • You don't want to use a lot of additional modules and each time the test after the upgrade
  • You don't want to look for additional patches, every time when you meet the next bug
  • You are trying to save RAM of server
  • The server doesn't allow to install other modules, for example, "drupalgardens" hosting
  • You want to have full control over the source code and be independent of the modules

Now I'll quickly show you how to implement such functionality in your custom theme using View only. The module already in the code in Drupal v8, so we will use this module for Drupal v7 only.

The structure of files.
The structure of the files.

Let's prepare the necessary. We need few JavaScript libraries and own JS for the own Drupal theme:

In brackets, I showed the version I used, you can download the latest version, however, you may need to change a couple of lines in scripts.js. Do not worry, usually, those libraries are stable ;-)

We also need to create a view! Just standard drupal view: Unformatted list, Use pager: Mini, Use AJAX: No. It's enough!

The next step, open scripts.js in your favorite editor and add a few pieces of code.

File
YOUTHEME.info
scripts[] = js/imagesloaded.pkgd.min.js
scripts[] = js/isotope.pkgd.min.js
scripts[] = js/infinite-scroll/jquery.infinitescroll.min.js
scripts[] = js/infinite-scroll/behaviors/manual-trigger.js
scripts[] = js/scripts.js

These lines add the required plugins and libraries to your theme.  You can also read more about managing javascript in drupal there.

File
scripts.js
/**
 * Apply imagesLoaded, isotope and infinitescroll for the view.
 * 
 * @type {{attach: Drupal.behaviors.isotopeAndInfiniteScroll.attach}}
 */
Drupal.behaviors.isotopeAndInfiniteScroll = {
  attach: function (context, settings) {
 
    var $YOUR_VIEW_Container = $('.YOUR-VIEW-CLASS .view-content', context),
      $pager = $('ul.pager', context);
 
    $YOUR_VIEW_Container.imagesLoaded(function () {
      $YOUR_VIEW_Container.isotope({
        itemSelector: '.views-row'
      });
    });
 
    $YOUR_VIEW_Container.infinitescroll({
      navSelector: 'ul.pager', // Selector for the paged navigation (it will be hidden)
      nextSelector: 'ul.pager .pager-next a', // Selector for the NEXT link (to page 2)
      itemSelector: '.views-row', // Selector for all items you'll retrieve
      loading: {
        finishedMsg: '<em>' + Drupal.t('We don\'t have such content anymore!') + '</em>',
        img: 'http://i.imgur.com/qkKy8.gif', // Preloader.
        msgText: '<em>' + Drupal.t('Loading!') + '</em>'
      },
      debug: false,
      state: {
        // The string is very important because drupal starts from page = 0, 
        // however "infinite scroll" except 1, so we override.
        currPage: 0
      },
      behavior: 'twitter',
      animate: true,
      errorCallback: function () {
      }
    }, function (arrayOfNewElements) {
      var $newElements = $(arrayOfNewElements).css({
        opacity: 0
      });
 
      $newElements.imagesLoaded(function () {
        $newElements.animate({
          opacity: 1
        });
        $YOUR_VIEW_Container.isotope('appended', $newElements);
      });
    });
 
 
    if ($YOUR_VIEW_Container.length > 0) {
      $pager.find('.pager-next a').text('load more');
      // How to Get "Twitter-style triggered infinite scroll"
      // https://github.com/paulirish/infinite-scroll/issues/520
      $('.view-content').infinitescroll('manual');
    }
 
  }
};

To be honest, a few years ago, I met one bug. After loading the next page isotope grid was broken. I had little time for decision and found a quick fix, see the timeline 49-54 (from if ($YOUR_VIEW_Container.length > 0)). Maybe you know the best solution. Nevertheless, it works perfectly.

File
style.scss
// To make some CSS styling.
.view-id-ideas_marathon {
  .views-row {
    padding: 7px;
    vertical-align: middle;
    text-align: center;
    background-color: #FFF;
    width: 25%;
    &:before {
      content: '';
    }
  }
  // To hide the some links in the pager. We want to see "Next" link only.
  .pager-previous,
  .pager-current {
    display: none;
  }
}

It remains quite a bit, make it look more beautiful. In my example, I used SASS (scss), you can use just CSS if you prefer.

Conclusion

As you can see, sometimes it is possible to build a complex in a simple way. Without heavy modules, without the additional support of these modules, without the infinite pushing of settings in the admin section. Make drupal easy!

The real results:

View with content
A part of view with paginator