How to implement Isotope with Pagination
Asked Answered
A

4

49

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});
      }); 
});
Antilles answered 19/1, 2016 at 1:29 Comment(5)
which line is the error Uncaught TypeError: Cannot read property '[object Array]' of undefined generated on?Landloper
@Landloper jquery.isotope.min.js:13 Uncaught TypeError: Cannot read property '[object Array]' of undefinedAntilles
Are you sure you copy/pasted your entire script? Because it looks like your last two chunks (starting with Initialize counters..) are outside the scope of the jQuery ready IIFE. If that's the case, $container won't be defined and maybe thats the TypeError.Grenville
I think you have an error in this line: $('.isotope').load(href +".html .isotope > *"); That should be: $('.isotope').load(href +" .html .isotope > *"); ( a space char is missing between +" and .html). This space is necessary to make jquery understand that you're using the special syntax that picks up only a part of the incoming page... This might mean that the whole entire returned page would be added to the .isotope element, which might result in all other functions not working properly as the do not find elements in the expected position in the hierarchy of the page.Hanus
Also, another problem: you define the $items variable value ONLY in startup call: this means that this variable will contain the items that are in the page AT startup time, not the ones that are now in the page: If the container contains A,B,C, that means that at page init you assign $items to A,B,C. Then you call .load, and the container content is now D,E,F, BUT $items STILL contains A,B,C! So, you must add $items = $('.item'); just before container.append(... or else this would not work: if you don't do that, you'll always call isotope on A,B,C, and that is exactly what's happening!Hanus
C
2

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
    }
});
Clearwing answered 22/9, 2019 at 10:41 Comment(0)
R
1

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
    }
});
Ramonitaramos answered 29/4, 2017 at 21:5 Comment(1)
that's filter not pagination!Pensioner
S
0

Check below link if usefull

https://mixitup.kunkalabs.com/extensions/pagination/

You can also use lazy loder for pagination.

Hope this'll help you

Sonnnie answered 28/1, 2016 at 13:14 Comment(2)
Thanks, but it warns of using more than 150 items. I need to be able to filter through a lot more than that.Antilles
This is solution written for wordpress but does show the idea to implement pagination, hope this helps... tannermoushey.com/2012/12/isotope-pagingMarchpane
O
-1

<a href="http://codepen.io/Igorxp5/pen/ojJLQE"></a>

I think this will help you.

Refer this URL

Opener answered 21/12, 2016 at 10:29 Comment(2)
Bro, you need to provide some accompanying code too when posting codepen/fiddle. Try copying some code from over there, and phrasing it in a manner which could answer this question.Odelsting
Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline.Alwin

© 2022 - 2024 — McMap. All rights reserved.