Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement Isotope with Pagination

I am trying to implement isotope with pagination on my WordPress site (which obviously is a problem for most people). I've come up with a scenario which may work if I can figure a few things out.

On my page, I have this part of my isotope script -

$('.goforward').click(function(event) {
    var href = $(this).attr('href');
    $('.isotope').empty();
    $('.isotope').load(href +".html .isotope > *");
    $( 'div.box' ).addClass( 'isotope-item' );
    $container.append( $items ).isotope( 'insert', $items, true );
    event.preventDefault();
});

Then I am using this pagination function which I modified from here to have the 'goforward' class --

function isotope_pagination($pages = '', $range = 2)
{  
     $showitems = ($range * 2)+1;  

     global $paged;
     if(empty($paged)) $paged = 1;

     if($pages == '')
     {
         global $wp_query;
         $pages = $wp_query->max_num_pages;
         if(!$pages)
         {
             $pages = 1;
         }
     }   

     if(1 != $pages)
     {
         echo "<div class='pagination'>";
         for ($i=1; $i <= $pages; $i++)
         {
             if (1 != $pages &&( !($i >= $paged+$range+1 || $i <= $paged-$range-1) || $pages <= $showitems ))
             {
                 echo ($paged == $i)? "<a href='".get_pagenum_link($i)."' class='inactive goforward'>".$i."</a>":"<a href='".get_pagenum_link($i)."' class='inactive goforward' >".$i."</a>";
             }
         }
         echo "</div>\n";
     }
}

1st Problem - I'm having issues with the filtering/sorting. It filters fine for the first page, but doesn't sort. On the second page or any other page loaded it does not append/insert or even filter/sort when starting fresh on that page. Instead, when trying to do so it gives me this error --

Uncaught TypeError: Cannot read property '[object Array]' of undefined

2nd Problem - When loading the page fragments, there's a delay and the current page is still visible before the next page fragment is loaded in its place.

I know a lot of people have problems with isotope and pagination, usually, end up using infinite scroll even though isotope author does not recommend it.

So my theory is loading content via load() and have a callback of some sort to only display filtered items.

Any ideas on how to achieve this?

My entire isotope script ---

$(function () {
    var selectChoice, updatePageState, updateFiltersFromObject,
    $container = $('.isotope');
    $items = $('.item');  

    ////////////////////////////////////////////////////////////////////////////////////
    /// EVENT HANDLERS
    ////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////
        // Mark filtering element as active/inactive and trigger filters update
        $('.js-filter').on( 'click', '[data-filter]', function (event) {
          event.preventDefault();
          selectChoice($(this), {click: true});
          $container.trigger('filter-update');
        });
        //////////////////////////////////////////////////////
        // Sort filtered (or not) elements
        $('.js-sort').on('click', '[data-sort]', function (event) {
          event.preventDefault();
          selectChoice($(this), {click: true});
          $container.trigger('filter-update');
        });
        //////////////////////////////////////////////////////
        // Listen to filters update event and update Isotope filters based on the marked elements
        $container.on('filter-update', function (event, opts) {
          var filters, sorting, push;
          opts = opts || {};
          filters = $('.js-filter li.active a:not([data-filter="all"])').map(function () {
            return $(this).data('filter');
          }).toArray();
          sorting = $('.js-sort li.active a').map(function () {
            return $(this).data('sort');
          }).toArray();
          if (typeof opts.pushState == 'undefined' || opts.pushState) {
            updatePageState(filters, sorting);
          }
          $container.isotope({
            filter: filters.join(''),
            sortBy: sorting
          });

        });
        //////////////////////////////////////////////////////
        // Set a handler for history state change
        History.Adapter.bind(window, 'statechange', function () {
          var state = History.getState();
          updateFiltersFromObject(state.data);
          $container.trigger('filter-update', {pushState: false});
        });
        ////////////////////////////////////////////////////////////////////////////////////
        /// HELPERS FUNCTIONS
        ////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////
        // Build an URI to get the query string to update the page history state
        updatePageState = function (filters, sorting) {
          var uri = new URI('');
          $.each(filters, function (idx, filter) {
            var match = /^\.([^-]+)-(.*)$/.exec(filter);
            if (match && match.length == 3) {
              uri.addSearch(match[1], match[2]);
            }
          });
          $.each(sorting, function (idx, sort) {
            uri.addSearch('sort', sort);
          });
          History.pushState(uri.search(true), null, uri.search() || '?');
        };
        //////////////////////////////////////////////////////
        // Select the clicked (or from URL) choice in the dropdown menu
        selectChoice = function ($link, opts) {
          var $group = $link.closest('.btn-group'),
              $li = $link.closest('li'),
              mediumFilter = $group.length == 0;
          if (mediumFilter) {
            $group = $link.closest('.js-filter');
          }

          if (opts.click) {
            $li.toggleClass('active');
          } else {
            $li.addClass('active');
          }
          $group.find('.active').not($li).removeClass('active');
          if (!mediumFilter) {
            if ($group.find('li.active').length == 0) {
              $group.find('li:first-child').addClass('active');
            }
            $group.find('.selection').html($group.find('li.active a').first().html());
          }
        };
        //////////////////////////////////////////////////////
        // Update filters by the values in the current URL
        updateFiltersFromObject = function (values) {
          if ($.isEmptyObject(values)) {
            $('.js-filter').each(function () {
                selectChoice($(this).find('li').first(), {click: false});
            });
            selectChoice($('.js-sort').find('li').first(), {click: false});
          } else {
            $.each(values, function (key, val) {
              val = typeof val == 'string' ? [val] : val;
              $.each(val, function (idx, v) {
                var $filter = $('[data-filter=".' + key + '-' + v + '"]'),
                    $sort = $('[data-sort="' + v + '"]');
                if ($filter.length > 0) {
                  selectChoice($filter, {click: false});
                } else if ($sort.length > 0) {
                  selectChoice($sort, {click: false});
                }
              });
            });
          }
        };
        ////////////////////////////////////////////////////////////////////////////////////
        /// Initialization
        ////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////
        // Initialize Isotope
    $container.imagesLoaded( function(){
        $container.isotope({
            masonry: { resizesContainer: true },
            itemSelector: '.item',
            getSortData: {
                date: function ( itemElem ) {
                    var date = $( itemElem ).find('.thedate').text();
                    return parseInt( date.replace( /[\(\)]/g, '') );
                },
            area: function( itemElem ) { // function
                var area = $( itemElem ).find('.thearea').text();
                return parseInt( area.replace( /[\(\)]/g, '') );
            },
            price: function( itemElem ) { // function
                var price = $( itemElem ).find('.theprice').text();
                return parseInt( price.replace( /[\(\)]/g, '') );
            }
        }
    });

    var total = $(".next a:last").html();
    var pgCount = 1;
    var numPg = total;
    pgCount++;

    $('.goback').click(function() {
        $('.isotope').empty();
        $('.isotope').load("/page/<?php echo --$paged;?>/?<?php echo $_SERVER["QUERY_STRING"]; ?>.html .isotope > *");
        $container.append( $items ).isotope( 'insert', $items, true );
        $( 'div.box' ).addClass( 'isotope-item' );
   });

   $('.goforward').click(function(event) {
       var href = $(this).attr('href');
       $('.isotope').empty();
       $('.isotope').load(href +".html .isotope > *");
       $( 'div.box' ).addClass( 'isotope-item' );
       $container.append( $items ).isotope( 'insert', $items, true );
       event.preventDefault();
   });
});
        //////////////////////////////////////////////////////
        // Initialize counters
        $('.stat-count').each(function () {
          var $count = $(this),
              filter = $count.closest('[data-filter]').data('filter');
          $count.html($(filter).length);
        });
        //////////////////////////////////////////////////////
        // Set initial filters from URL
        updateFiltersFromObject(new URI().search(true));
        $container.trigger('filter-update', {pushState: false});
      }); 
});
like image 502
730wavy Avatar asked Jan 19 '16 01:01

730wavy


2 Answers

lazy loader works quite well,i've tried it myself check codepen

you can also try:

var $container = $('#container').isotope({
    itemSelector: itemSelector,
    masonry: {
        columnWidth: itemSelector,
        isFitWidth: true
    }
});
like image 135
Akanimo Avatar answered Nov 02 '22 05:11

Akanimo


Have you checked the following link:

https://codepen.io/Igorxp5/pen/ojJLQE

It has a working example of isotope with pagination.

Have a look at the following block of code from the JS section:

var $container = $('#container').isotope({
    itemSelector: itemSelector,
    masonry: {
        columnWidth: itemSelector,
        isFitWidth: true
    }
});
like image 1
Wolfack Avatar answered Nov 02 '22 04:11

Wolfack