patch to solve bug with the views module masonry

CommentFileSizeAuthor
#1 support_masonry.patch476 bytesguilopes
support_masonry.patch0 bytesguilopes

Comments

guilopes’s picture

StatusFileSize
new476 bytes
almc’s picture

I've tested the current Masonry with Views Load More and this patch, and it works, thank you.

zmove’s picture

Status: Needs review » Reviewed & tested by the community

Patch works well.

adamgerthel’s picture

Uhm, by looking a the code- it doesn't seem to handle any scenarios when Masonry isn't available. You've added:

wrapper.find('.view-content').masonry('reload');

But calling masonry without actually having masonry will most likely cause a js error, no?

kenppx’s picture

When I apply this patch actually it works well when I use masonry.
But when masonry is not available we have a js error.
How can I solve this problem?

kenppx’s picture

I am not familiar with jquery and javascript.
But I wrote this and it works well.

     if(0 < $(".masonry").size()){
    // Reload masonry - Support masonry views
     wrapper.find('.view-content').masonry('reload');
     }
kenppx’s picture

I have another problem.
Now I am using Views Load More+waypoint with Masonry API+masonry views.
My test web site is below.

http://153.121.53.235/postwall/

When I scroll down to the bottom of the page, sometimes infinite scroll does not work.
But then I scroll up the page, suddenly page loading starts.
My assumption is like this, Waypoint calculates the height of content before masonry
finish rendering of all blocks. So Waypoint can not detect the correct height.
If I can load waypoint after rendering of masonry block, problem may be solved.
But I do not have enough knowledge to solve this problem.
If you have any idea could you help me?
Thank you.

socialnicheguru’s picture

#6 worked better. without the if statement, I get a masonry undefined error

m4olivei’s picture

Status: Reviewed & tested by the community » Closed (won't fix)

Humm, the views_load_more.js file is not the place to make calls to masonry. Notice that at the end of Drupal.ajax.prototype.commands.viewsLoadMoreAppend(), views_load_more module calls Drupal.attachBehaviors(wrapper, settings);. That will fire all the the attach() methods on all registered Drupal.behaviors objects. That is where you should doing whatever is necessary to re-init masonry.

See https://www.drupal.org/node/756722#behaviors. Also google "Drupal.behaviors" to find some info on the topic. Hope that helps.

As such, won't commit.

dmitrii’s picture

use drupal_add_js() in theme/custom module to add following js code to fix masonry with the Views Load More module.

(function($) {

  // Add masonry support
  Drupal.behaviors.masonryFix = {
    attach: function(context, settings) {
      if (settings && settings.viewsLoadMore && settings.views && settings.views.ajaxViews) {
        $.each(settings.viewsLoadMore, function(i, setting) {
          var view = '.view-id-' + setting.view_name + '.view-display-id-' + setting.view_display_id + ' > .view-content';
          if ($(view).masonry) {
            $(view).masonry('appended', context);
          }
        });
      }
    }
  };

})(jQuery);
phm’s picture

@dmitrii:
I tried this but settings.viewsLoadMore is undefined while the module is working fine otherwise. I can't figure out why.

tostinni’s picture

Views load more trigger views_load_more.new_content when new content is loaded so we can use this code in our theme :

(function ($) {
  $(window).bind('views_load_more.new_content', function(){
    // Reload the masonry view after "load more"
    $('.view-VIEW_MACHINE_NAME .view-content').masonry('reload');
  });
  
})(jQuery);

Just replace VIEW_MACHINE_NAME by your view machine name and it should work.

guilopes’s picture

the best way is #12 in my opinion

shabirahmad’s picture

Hi Guys,

I am using masonry views module and creating a slideshow like the one on the link http://www.theclientsserver.com/clients/witte/

I have configured the module but the height of the view is not uniform (check the screenshot http://i.imgur.com/Tk5HSR3.png). How can I fix the view. also I am unable to apply vertical gutter as the margin is not working on absolutely positioned div.

Any idea will highly be appreciated

Thansk

marcelovani’s picture

Here is my solution:

Add a js file with the following:

(function ($) {

Drupal.ajax.prototype.commands.viewsMasonry = function (ajax, command) {
    jQuery(command.selector).masonry(command.method);
};

})(jQuery);

This will make the command available to the ajax callback.

Now create a hook to alter the view and add the command to reload masonry

/**
 * Implements hook_views_ajax_data_alter().
 */
function mymodule_views_ajax_data_alter(&$commands, $view) {
  // Reload masonry after new items are appended to the view.
  if (is_a($view->query->pager, 'views_plugin_pager_load_more')) {
    $command = array(
      'command' => 'viewsMasonry',
      'method' => 'reload',
      'selector' => '.view-dom-id-' . $view->dom_id . ' .view-content',
    );
    $commands[] = $command;
  }
}

This will trigger the method reload, that will be passed to viewsMasonry.
You can use other methods if you want.
Also, as a selector I am automatically getting the id of the view.

socialnicheguru’s picture

in #15 in which js file do you put the code?

marcelovani’s picture

You can save it with your modules and use drupal_add_js to include the it.
i.e.

drupal_add_js(drupal_get_path('module', 'mymodule') . '/js/mymodule.js')

One important thing that I forgot to mention, initially you will need to attach another behaviour to initialise the masonry
i.e.

Drupal.behaviors.mymodule = {
  attach : function(context) {
    jQuery('.view-name .view-content').masonry({
        itemSelector: '.view-rows',
        columnWidth: 200,
        isFitWidth: true,
    });
  },
};

This can be added on the same js example as above, right beneath "(function ($) {"

garethhallnz’s picture

None of the above worked amazingly for me (Note I did not try #15)

I added the below to the theme's js file and seems to work.

  $(window).bind('load', function() {
    Drupal.behaviors.YOUR_THEME_NAMEMasonryViewsLoadMoreFix = {
      attach: function(context, settings) {
        if (settings && settings.views && settings.views.ajaxViews && settings.masonry) {
          $.each(settings.masonry, function(view, setting) {
            if ($(view).masonry) {
              $(view).masonry('appended', context, true);
            }
          });
        }
      }
    };
  });
bmpinto’s picture

My way of solving this was to override jQuery's append function to trigger an event everytime something is appended to the container.

;(function($){
  // jQuery override to trigger an event everytime something is appended
  var coreAppend = $.fn.append;
  $.fn.append = function () {
    return coreAppend.apply(this, arguments).trigger('append');
  };

  var packery = {
    init: function() {
      this.bindElements();
      this.bindEvents();
      this.layoutInit();
    },

    // initialize DOM elements and packery options
    bindElements: function() {
      this.$container = $('.view-content');
      this.$selector = '.views-row';
      this.$packeryOptions = {
        itemSelector: this.$selector,
        gutter: 30,
        transitionDuration: 0
      };
    },

    // draw packery layout on init
    layoutInit: function() {
      this.$container.packery(this.$packeryOptions);
    },

    // triggered everytime "views load more" appends to the container
    bindEvents: function() {
      this.$container.bind('append', this.reload);
    },

    // reload packery layout on append
    reload: function() {
      $(this).packery('reloadItems');
    }
  };

  // let drupal handle packery initialization
  Drupal.behaviors.packery = {
    attach : function(context) {
      packery.init();
    }
  };
})(jQuery);

I'm using packery instead of masonry but it's not difficult to adapt.

johnny5th’s picture

Got this to work on mine with this

Drupal.behaviors.MasonryViewsLoadMoreFix = {
    attach: function(context, settings) {
      if (settings && settings.views && settings.views.ajaxViews && settings.masonry) {
        $.each(settings.masonry, function(view, setting) {
          if ($(view).masonry) {
            $(view).imagesLoaded( function() {
              $(view).masonry('layout');
            });
          }
        });
      }
    }
  };