georgewatson
georgewatson

Reputation: 125

Making smoothState animations and Masonry work together

I'm trying to use Masonry and smoothState together using SmoothState animations between pages.

The code below makes smoothState animations work both forwards and in reverse:

$(function(){
  'use strict';
  var $page = $('#main'),
      options = {
        debug: true,
        prefetch: true,
        cacheLength: 2,
        onStart: {
          duration: 500, // Duration of our animation
          render: function ($container) {
            // Add your CSS animation reversing class
            $container.addClass('is-exiting');
            // Restart your animation
            smoothState.restartCSSAnimations();
          }
        },
        onReady: {
          duration: 0,
          render: function ($container, $newContent) {
            // Remove your CSS animation reversing class
            $container.removeClass('is-exiting');
            // Inject the new content
            $container.html($newContent);
          }
        }
      },
      smoothState = $page.smoothState(options).data('smoothState');
});

I can make Masonry work by invoking

$(document).ready(function() {
    var $container = $('#portfolio');
    $container.imagesLoaded( function() {
      $container.masonry({
        itemSelector : '.p-item',
      });    
    });
});

But they don't play nicely together. Masonry works, but smoothState doesn't (the forward animations are still fine, because they're pure CSS, but the JS doesn't seem to work). If I get rid of the Masonry code, smoothState works fine, which seems odd because they ought to be unrelated.

Is there a way to have both?

Upvotes: 0

Views: 1005

Answers (1)

benpalmer
benpalmer

Reputation: 2098

According to the FAQ, the $(document).ready functions must be re-initialised in the onAfter. After looking at lots of articles in the issues section and here, the developer has created a gist here that re-runs any $(document).ready functions.

I still can't get it working though (I'm not using masonry but using imagesLoaded from desandro and some other plugins), seems $.readyFn.execute(); is supposed to run on option.callback but the FAQs say to run onAfter callback. I have tried both and it's not worked for me, I've also tried removing all other plugins and just doing some menial task on ready but that didn't work, seems onAfter just doesn't fire for me.

So even though this doesn't work for me, according to other posts this should fix it for you.

Paste in the following right after including jQuery

;(function($){
    var  $doc = $(document);

    /** create mod exec controller */
    $.readyFn = {
        list: [],
        register: function(fn) {
            $.readyFn.list.push(fn);
        },
        execute: function() {
            for (var i = 0; i < $.readyFn.list.length; i++) {
                try {
                   $.readyFn.list[i].apply(document, [$]);
                }
                catch (e) {
                    throw e;
                }
            };
        }
    };

    /** run all functions */
    $doc.ready(function(){
        $.readyFn.execute();
    });

    /** register function */
    $.fn.ready = function(fn) {
        $.readyFn.register(fn);
    };

})(jQuery);

Then add the following, make sure the original masonry call is inside a $(document).ready function

$(function(){
  'use strict';
  var $page = $('#main'),
      options = {
        debug: true,
        prefetch: true,
        cacheLength: 2,
        onStart: {
          duration: 500, // Duration of our animation
          render: function ($container) {
            // Add your CSS animation reversing class
            $container.addClass('is-exiting');
            // Restart your animation
            smoothState.restartCSSAnimations();
          }
        },
        onReady: {
          duration: 0,
          render: function ($container, $newContent) {
            // Remove your CSS animation reversing class
            $container.removeClass('is-exiting');
            // Inject the new content
            $container.html($newContent);
          }
        },
        // over a year ago, this was simply callback: function(){}
        onAfter: function($container, $newContent){
          $.readyFn.execute();
        }
      },
      smoothState = $page.smoothState(options).data('smoothState');
});

Upvotes: 1

Related Questions