quarky
quarky

Reputation: 748

Masonry destroy and initialize again

I have initialize masonry plugin - works OK,

than I destroy it for media width <= 767px - it was destroyed

but when I return back to media width > 767px and initialize masonry again it doesn't work.

why?

or is there any another solution to turn off masonry plugin and later turn it on on some event?

this is my code:

var masonryData = {
    isInitLayout: true,
    isResizeBound: false,
    itemSelector: '.item',
    columnWidth: 300,
    gutter: 20,
    transitionDuration: '0.5s'
};

function initializeMasonry(masonryData){
    if (jQuery().masonry) {
        var masonryContainer = jQuery('.masonry').masonry(masonryData);
        jQuery(masonryContainer).imagesLoaded(function(){
            jQuery(masonryContainer).masonry(masonryData);
        });
    }
}

function destroyMasonry(){
    if (jQuery().masonry) {
        jQuery('.masonry').masonry();
        jQuery('.masonry').masonry('destroy');
    }
}

I'm using enquire plugin so I use match/unmatch methods for js media queries:

$.Site.Match.smallScreen = function() {
   ...
   destroyMasonry();
   ...
}

$.Site.Match.mediumScreen = function() {
   ...
   initializeMasonry(masonryData);
   ...
}

Many thanks for help

Upvotes: 2

Views: 12192

Answers (4)

Finally after hours of reading the docs, I found that masonry will make a $.data('masonry') to masonry element.

You can read more about it in masonry docs here.

This data will affect the items position in masonry. So, we need to remove this data with $.removeData('masonry') after we destroy the masonry.

// init masonry
$('.masonry-container').masonry();

// destroy masonry
$('.masonry-container').masonry('destroy');
$('.masonry-container').removeData('masonry'); // This line to remove masonry's data

// re-init masonry again. The position will be nice
$('.masonry-container').masonry();

Upvotes: 7

Hussard
Hussard

Reputation: 676

Eli Gassert's answer might be more clever than going all javascript.

However, I found myself doing this quite successfully like this:

$(window).on('resize', function (event) {
  var $window = $(window);

  if ($window.width() < 768) {
    var $masonryTarget = $('.masonry-container'),
        $hasMasonry = $masonryTarget.data('masonry') ? true : false
    ;
    if ($masonryTarget.length > 0 && $hasMasonry) {
      // Destroy masonry if exists.
      $masonryTarget.masonry('destroy');
    }
  } else {
    // Enable all masonry instances.
    $('.mansonry-container').masonry({
      'itemSelector': '.masonry-item',
      'columnWidth': '.masonry-item'
    });
  }
});

The basic idea is that masonry, initialized as a jQuery plugin is stored in a data attribute. If a masonry data attribute is defined, we destroy the instance.

Might be worth mentioning that debouncing this function improves a lot the performance.

Upvotes: 1

Eli Gassert
Eli Gassert

Reputation: 9763

For what it's worth, I ended up solving this a different way. Masonry is just setting some styles. So using a media query, I set the following CSS to basically render masonry useless:

@media (max-width: 768px) {
  .item {
    position: relative !important;
    left: auto !important;
    top: auto !important;
  }
}

Now, I always initialize masonry, and never uninitialize/reinitialize it. It's on all the time, but CSS media queries with !important take priority over the inline styles set by Masonry.

Upvotes: 3

Libor Pt&#225;ček
Libor Pt&#225;ček

Reputation: 1

$(document).ready(function() {

if ($(window).width() <= 767) {

    $('#container').masonry( 'destroy' );

} 

if ($(window).width() > 768) {

    $('#container').masonry({
      columnWidth: 350,
      gutter: 20,
    });

} 

if ($(window).width() > 992) {

    $('#container').masonry({
      columnWidth: 300,
      gutter: 20,
    });

} 


if ($(window).width() > 1200) {

    $('#container').masonry({
      columnWidth: 270,
      gutter: 20,
    });

}

});

Upvotes: -1

Related Questions