Trying to integrate isotope filter with pagination using OR logic

Viewed 995

I'm having a difficult problem trying to solve an issue with my filters not displaying the correct items properly. When tap a selection it does not show the correct item properly despite having the correct class name with the element.

When I select beige on the list of choices it does filter it properly. Only when I select the next item to filter yellow it shows the previous color beige

The pagination function breaks if coupled using an OR logic

function goToPage(n) {
    currentPage = n;
    var selector = itemSelector;
    var inclusives = [];
    var exclusives = [];

    // for each box checked, add its value and push to array
    $checkboxes.each( function( i, elem ) {
        // if checkbox, use value if checked
        if ( elem.checked ) {
        selector = '.'+elem.value + ' ';
        // selector += '.'+elem.value + ' ';
        inclusives.push(selector);
        }
    });



    // smash all values back together for 'OR' filtering
    filterValue = inclusives.length ? inclusives.join(', ') : '*';

    
    // add page number to the string of filters
    var wordPage = currentPage.toString();
    filterValue += ('.'+wordPage);
    
    $container.isotope({ filter: filterValue });
    changeFilter(filterValue);
    
}

If I tried using an AND logic the filter with pagination works fine

function goToPage(n) {
    currentPage = n;
    var selector = itemSelector;
    var exclusives = [];
        // for each box checked, add its value and push to array
        $checkboxes.each(function (i, elem) {
            if (elem.checked) {
                selector += ( currentFilter != '*' ) ? '.'+elem.value : '';
                exclusives.push(selector);
            }
        });
        // smash all values back together for 'and' filtering
        filterValue = exclusives.length ? exclusives.join('') : '*';
        
        // add page number to the string of filters
        var wordPage = currentPage.toString();
        filterValue += ('.'+wordPage);
   
    changeFilter(filterValue);
}

var itemSelector = ".products-item"; 
var $checkboxes = $('.filter-checkbox');
var $container = $('.products-container').isotope({ itemSelector: itemSelector });

//Ascending order
var responsiveIsotope = [ [480, 3] , [720, 5] ];
var itemsPerPageDefault = 5;
var itemsPerPage = defineItemsPerPage();
var currentNumberPages = 1;
var currentPage = 1;
var currentFilter = '*';
var filterAttribute = 'data-filter';
var filterValue = "";
var pageAttribute = 'data-page';
var pagerClass = 'isotope-pager';

// update items based on current filters    
function changeFilter(selector) { $container.isotope({ filter: selector }); }

//grab all checked filters and goto page on fresh isotope output
function goToPage(n) {
    currentPage = n;
    var selector = itemSelector;
    var inclusives = [];
    var exclusives = [];

    // for each box checked, add its value and push to array
    $checkboxes.each( function( i, elem ) {
        // if checkbox, use value if checked
        if ( elem.checked ) {
        selector = '.'+elem.value + ' ';
        // selector += '.'+elem.value + ' ';
        inclusives.push(selector);
        }
    });



    // smash all values back together for 'and' filtering
    filterValue = inclusives.length ? inclusives.join(', ') : '*';

    
    // add page number to the string of filters
    var wordPage = currentPage.toString();
    filterValue += ('.'+wordPage);
    
    $container.isotope({ filter: filterValue });
    changeFilter(filterValue);
    
}

// determine page breaks based on window width and preset values
function defineItemsPerPage() {
    var pages = itemsPerPageDefault;

    for( var i = 0; i < responsiveIsotope.length; i++ ) {
        if( $(window).width() <= responsiveIsotope[i][0] ) {
            pages = responsiveIsotope[i][1];
            break;
        }
    }
    return pages;
}

function setPagination() {

    var SettingsPagesOnItems = function(){
        var itemsLength = $container.children(itemSelector).length;
        var pages = Math.ceil(itemsLength / itemsPerPage);
        var item = 1;
        var page = 1;
        var selector = itemSelector;
        var exclusives = [];
            // for each box checked, add its value and push to array
            $checkboxes.each(function (i, elem) {
                if (elem.checked) {
                    selector += ( currentFilter != '*' ) ? '.'+elem.value : '';
                    exclusives.push(selector);
                }
            });
            // smash all values back together for 'OR' filtering
            filterValue = exclusives.length ? exclusives.join('') : '*';
            // find each child element with current filter values
            $container.children(filterValue).each(function(){
                // increment page if a new one is needed
                if( item > itemsPerPage ) {
                    page++;
                    item = 1;
                }
                // add page number to element as a class
                wordPage = page.toString();
                
                var classes = $(this).attr('class').split(' ');
                var lastClass = classes[classes.length-1];
                // last class shorter than 4 will be a page number, if so, grab and replace
                if(lastClass.length < 4){
                    $(this).removeClass();
                    classes.pop();
                    classes.push(wordPage);
                    classes = classes.join(' ');
                    $(this).addClass(classes);
                } else {
                    // if there was no page number, add it
                    $(this).addClass(wordPage); 
                }
                item++;
            });
        currentNumberPages = page;
    }();

    // create page number navigation
    var CreatePagers = function() {

        var $isotopePager = ( $('.'+pagerClass).length == 0 ) ? $('<div class="'+pagerClass+'"></div>') : $('.'+pagerClass);

        $isotopePager.html('');
        if(currentNumberPages > 1){
            for( var i = 0; i < currentNumberPages; i++ ) {
                var $pager = $('<a href="javascript:void(0);" class="pager" '+pageAttribute+'="'+(i+1)+'"></a>');
                    $pager.html(i+1);

                    $pager.click(function(){
                        var page = $(this).eq(0).attr(pageAttribute);
                        goToPage(page);
                    });
                $pager.appendTo($isotopePager);
            }
        }
        $container.after($isotopePager);
    }();
}
// remove checks from all boxes and refilter
function clearAll(){
    $checkboxes.each(function (i, elem) {
        if (elem.checked) {
            elem.checked = null;
        }
    });
    currentFilter = '*';
    setPagination();
    goToPage(1);
}

setPagination();
goToPage(1);

//event handlers
$checkboxes.change(function(){
    var filter = $(this).attr(filterAttribute);
    currentFilter = filter;
    setPagination();
    goToPage(1);
});

$('#clear-filters').click(function(){clearAll()});

 
/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
    display: block;
}
body {
    line-height: 1;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}



.centered-component {
    width : 100%;
    max-width : 1300px;
    margin : 0 auto;
    display : flex;
    flex-wrap : wrap;
    padding : 100px 0;
}

.centered-component .filter-sidebar {
    width : 100%;
    max-width : 250px;
    margin-right : 24px;
}

.centered-component .content-block {
    flex : 1;
} 

.filter-sidebar {
    display : flex;
    flex-direction: column;
}

.products-container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap : 24px;
}

.isotope-container > h2{
    margin-bottom :48px;
}

.products-item {
    position: relative !important;
    top : initial !important;
    left : initial !important;
}

.products-container {
    height : initial !important;
}

.isotope-pager {
    margin-top : 42px;
}

.isotope-container + .isotope-container {
    margin-top : 64px;
}
<!doctype html>

<html>


<head>
    <title>Isotope</title>
    <link rel="stylesheet" href="style.css" />

</head>

<body>
<div class="centered-component">
    <div class="filter-sidebar">
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="beige" />
            beige
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="green" />
            green
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="blue" />
            blue
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="orange" />
            orange
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="purple" />
            purple
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="pink" />
            pink
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="teal" />
            teal
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="yellow" />
            yellow
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="black" />
            black
        </label>


    </div>

    <div class="content-block">
        <div class="isotope-container">
            <h2 class="heading">Category 1</h2>
            
            <ul class="products-container">
                <li class="products-item beige">
                    <h2>beige</h2>
                </li>
                <li class="products-item green">
                    <h2>green</h2>
                </li>

                <li class="products-item blue">
                    <h2>blue</h2>
                </li>
                <li class="products-item orange">
                    <h2>orange</h2>
                </li>
                <li class="products-item purple">
                    <h2>purple</h2>
                </li>
                <li class="products-item pink">
                    <h2>pink</h2>
                </li>
                <li class="products-item teal">
                    <h2>teal</h2>
                </li>

                <li class="products-item yellow">
                    <h2>yellow</h2>
                </li>
                <li class="products-item black">
                    <h2>black</h2>
                </li>
                <li class="products-item beige">
                    <h2>beige</h2>
                </li>

            </ul>
        </div>

    </div>
    
</div>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.isotope/2.2.2/isotope.pkgd.min.js"></script>
<script src="filter.js  "></script>


</body>
</html>

3 Answers

There is an issue with you setPagination and goToPage functions. You are not correctly setting filter selectors, if you want both paging to behave correctly, both of them should use similar item filter to determine current filter.

I have updated both functions to fix that issue but you still have some refactoring to do to move common filter creating function in to separate function and use it in both places.

var itemSelector = ".products-item";
var $checkboxes = $('.filter-checkbox');
var $container = $('.products-container').isotope({
  itemSelector: itemSelector
});

//Ascending order
var responsiveIsotope = [
  [480, 3],
  [720, 5]
];
var itemsPerPageDefault = 5;
var itemsPerPage = defineItemsPerPage();
var currentNumberPages = 1;
var currentPage = 1;
var currentFilter = '*';
var filterAttribute = 'data-filter';
var filterValue = "";
var pageAttribute = 'data-page';
var pagerClass = 'isotope-pager';

// update items based on current filters    
function changeFilter(selector) {
  $container.isotope({
    filter: selector
  });
}

//grab all checked filters and goto page on fresh isotope output
function goToPage(n) {
  currentPage = n;
  var selector = itemSelector;
  var inclusives = [];
  var exclusives = [];

  // for each box checked, add its value and push to array
  $checkboxes.each(function(i, elem) {
    // if checkbox, use value if checked
    if (elem.checked) {
      inclusives.push(elem.value);
    }
  });

  // smash all values back together for 'and' filtering and add page number to the string of filters
  filterValue = inclusives.length ?
    inclusives.map(f => `.${f}.${currentPage}`).join(', ') :
    `*.${currentPage}`;

  changeFilter(filterValue);
}

// determine page breaks based on window width and preset values
function defineItemsPerPage() {
  var pages = itemsPerPageDefault;

  for (var i = 0; i < responsiveIsotope.length; i++) {
    if ($(window).width() <= responsiveIsotope[i][0]) {
      pages = responsiveIsotope[i][1];
      break;
    }
  }
  return pages;
}

function setPagination() {
  var SettingsPagesOnItems = function() {
    var itemsLength = $container.children(itemSelector).length;
    var pages = Math.ceil(itemsLength / itemsPerPage);
    var item = 1;
    var page = 1;
    var inclusives = [];
    // for each box checked, add its value and push to array
    $checkboxes.each(function(i, elem) {
      if (elem.checked) {
        var selector = `${itemSelector}.${elem.value}`;
        inclusives.push(selector);
      }
    });
    // smash all values back together for 'OR' filtering
    filterValue = inclusives.length ? inclusives.join(',') : '*';

    // find each child element with current filter values
    $container.children(filterValue).each(function() {
      // increment page if a new one is needed
      if (item > itemsPerPage) {
        page++;
        item = 1;
      }
      // add page number to element as a class
      wordPage = page.toString();

      var classes = $(this).attr('class').split(' ');
      var lastClass = classes[classes.length - 1];
      // last class shorter than 4 will be a page number, if so, grab and replace
      if (lastClass.length < 4) {
        $(this).removeClass();
        classes.pop();
        classes.push(wordPage);
        classes = classes.join(' ');
        $(this).addClass(classes);
      } else {
        // if there was no page number, add it
        $(this).addClass(wordPage);
      }
      item++;
    });
    currentNumberPages = page;
  }();

  // create page number navigation
  var CreatePagers = function() {

    var $isotopePager = ($('.' + pagerClass).length == 0) ? $('<div class="' + pagerClass + '"></div>') : $('.' + pagerClass);

    $isotopePager.html('');
    if (currentNumberPages > 1) {
      for (var i = 0; i < currentNumberPages; i++) {
        var $pager = $('<a href="javascript:void(0);" class="pager" ' + pageAttribute + '="' + (i + 1) + '"></a>');
        $pager.html(i + 1);

        $pager.click(function() {
          var page = $(this).eq(0).attr(pageAttribute);
          goToPage(page);
        });
        $pager.appendTo($isotopePager);
      }
    }
    $container.after($isotopePager);
  }();
}

// remove checks from all boxes and refilter
function clearAll() {
  $checkboxes.each(function(i, elem) {
    if (elem.checked) {
      elem.checked = null;
    }
  });
  currentFilter = '*';
  setPagination();
  goToPage(1);
}

setPagination();
goToPage(1);

//event handlers
$checkboxes.change(function() {
  var filter = $(this).attr(filterAttribute);
  currentFilter = filter;
  setPagination();
  goToPage(1);
});

$('#clear-filters').click(function() {
  clearAll()
});
/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}


/* HTML5 display-role reset for older browsers */

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
  display: block;
}

body {
  line-height: 1;
}

ol,
ul {
  list-style: none;
}

blockquote,
q {
  quotes: none;
}

blockquote:before,
blockquote:after,
q:before,
q:after {
  content: '';
  content: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

.centered-component {
  width: 100%;
  max-width: 1300px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  padding: 100px 0;
}

.centered-component .filter-sidebar {
  width: 100%;
  max-width: 250px;
  margin-right: 24px;
}

.centered-component .content-block {
  flex: 1;
}

.filter-sidebar {
  display: flex;
  flex-direction: column;
}

.products-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 24px;
}

.isotope-container>h2 {
  margin-bottom: 48px;
}

.products-item {
  position: relative !important;
  top: initial !important;
  left: initial !important;
}

.products-container {
  height: initial !important;
}

.isotope-pager {
  margin-top: 42px;
}

.isotope-container+.isotope-container {
  margin-top: 64px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.isotope/2.2.2/isotope.pkgd.min.js"></script>
<!--script src="filter.js  "></script-->

<div class="centered-component">
  <div class="filter-sidebar">
    <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="beige" />
            beige
        </label>
    <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="green" />
            green
        </label>
    <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="blue" />
            blue
        </label>
    <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="orange" />
            orange
        </label>
    <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="purple" />
            purple
        </label>
    <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="pink" />
            pink
        </label>
    <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="teal" />
            teal
        </label>
    <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="yellow" />
            yellow
        </label>
    <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="black" />
            black
        </label>
  </div>
  <div class="content-block">
    <div class="isotope-container">
      <h2 class="heading">Category 1</h2>

      <ul class="products-container">
        <li class="products-item beige">
          <h2>beige</h2>
        </li>
        <li class="products-item green">
          <h2>green</h2>
        </li>

        <li class="products-item blue">
          <h2>blue</h2>
        </li>
        <li class="products-item orange">
          <h2>orange</h2>
        </li>
        <li class="products-item purple">
          <h2>purple</h2>
        </li>
        <li class="products-item pink">
          <h2>pink</h2>
        </li>
        <li class="products-item teal">
          <h2>teal</h2>
        </li>

        <li class="products-item yellow">
          <h2>yellow</h2>
        </li>
        <li class="products-item black">
          <h2>black</h2>
        </li>
        <li class="products-item beige">
          <h2>beige</h2>
        </li>
      </ul>
    </div>
  </div>
</div>

The issue is due to having a trailing space in the selector before appending the page number which makes the selector of last selected element always invalid; e.g selecting beige then green results in:

.beige, .green .1

where it should be (if I got what you're using the pages for properly!)

.beige, .green.1

Do remove the trailing space before appending the page number

    function goToPage(n) {
        ...
        
        // add page number to the string of filters
        var wordPage = currentPage.toString();
        
        if (filterValue.endsWith(' '))
            filterValue = filterValue.slice(0, -1)
        filterValue += ('.'+wordPage);
        
        $container.isotope({ filter: filterValue });
        changeFilter(filterValue);
    }

Or simple don't append a space to the end of the selector when pushing it to inclusives array

Got the code working with inclusives method for goToPage function (using OR filter) like so:

(1) Since classes can't start with digits in CSS (must start with alphabets, underscores or hypens), to add a class for the current Page you are on, it should be ._1 or ._2. Code change could look like so:

var wordPage = currentPage.toString();
filterValue += (', ._'+wordPage); // ensures that classes are .black, ._1

(2) setPagination function should do the same with the class addition using pageNumber

wordPage = '_'+page.toString(); // added _ to make the class ._1 for page 1

Doing the above 2 changes, got the code working.

Potential Issue

In the goToPage(n) function, the current page is getting set as the value of n.

However, when you pick 2 different colors from 2 different pages, the classes SHOULD look like so:

.black, .pink, _.1, ._2

Instead it shows .black, .pink, ._1.

The ._2 class never shows up.

I feel the goToPage function could be given the value of n dynamically depending on the category to which the color belongs.

But I will leave that with you, I think you are still in the middle of writing this code.

Code snippet attached.

var itemSelector = ".products-item"; 
var $checkboxes = $('.filter-checkbox');
var $container = $('.products-container').isotope({ itemSelector: itemSelector });

//Ascending order
var responsiveIsotope = [ [480, 3] , [720, 5] ];
var itemsPerPageDefault = 5;
var itemsPerPage = defineItemsPerPage();
var currentNumberPages = 1;
var currentPage = 1;
var currentFilter = '*';
var filterAttribute = 'data-filter';
var filterValue = "";
var pageAttribute = 'data-page';
var pagerClass = 'isotope-pager';

// update items based on current filters    
function changeFilter(selector) { $container.isotope({ filter: selector }); }


//grab all checked filters and goto page on fresh isotope output
function goToPage(n) {
    currentPage = n;
    var selector = itemSelector;
    var inclusives = [];
    var exclusives = [];

    // for each box checked, add its value and push to array
    $checkboxes.each( function( i, elem ) {
        // if checkbox, use value if checked
        if ( elem.checked ) {
        selector = '.'+elem.value + ' ';
        // selector += '.'+elem.value + ' ';
        inclusives.push(selector);
        }
    });


    console.log("inclusives",inclusives);
    // console.log("exclusives",exclusives);

    // smash all values back together for 'and' filtering
    filterValue = inclusives.length ? inclusives.join(', ') : '*';

    
    // add page number to the string of filters
    var wordPage = currentPage.toString();
    filterValue += (', ._'+wordPage);

    console.log("filterValue",filterValue);
    
    $container.isotope({ filter: filterValue });
    changeFilter(filterValue);
}

// determine page breaks based on window width and preset values
function defineItemsPerPage() {
    var pages = itemsPerPageDefault;

    for( var i = 0; i < responsiveIsotope.length; i++ ) {
        if( $(window).width() <= responsiveIsotope[i][0] ) {
            pages = responsiveIsotope[i][1];
            break;
        }
    }
    return pages;
}

function setPagination() {

    var SettingsPagesOnItems = function(){
        var itemsLength = $container.children(itemSelector).length;
        var pages = Math.ceil(itemsLength / itemsPerPage);
        var item = 1;
        var page = 1;
        var selector = itemSelector;
        var exclusives = [];
            // for each box checked, add its value and push to array
            $checkboxes.each(function (i, elem) {
                if (elem.checked) {
                    selector += ( currentFilter != '*' ) ? '.'+elem.value : '';
                    exclusives.push(selector);
                }
            });
            // smash all values back together for 'OR' filtering
            filterValue = exclusives.length ? exclusives.join('') : '*';
            // find each child element with current filter values
            $container.children(filterValue).each(function(){
                // increment page if a new one is needed
                if( item > itemsPerPage ) {
                    page++;
                    item = 1;
                }
                // add page number to element as a class
                wordPage = '_'+page.toString();
                
                var classes = $(this).attr('class').split(' ');
                var lastClass = classes[classes.length-1];
                // last class shorter than 4 will be a page number, if so, grab and replace
                if(lastClass.length < 4){
                    $(this).removeClass();
                    classes.pop();
                    classes.push(wordPage);
                    classes = classes.join(' ');
                    $(this).addClass(classes);
                } else {
                    // if there was no page number, add it
                    $(this).addClass(wordPage); 
                }
                item++;
            });
        currentNumberPages = page;
    }();

    // create page number navigation
    var CreatePagers = function() {

        var $isotopePager = ( $('.'+pagerClass).length == 0 ) ? $('<div class="'+pagerClass+'"></div>') : $('.'+pagerClass);

        $isotopePager.html('');
        if(currentNumberPages > 1){
            for( var i = 0; i < currentNumberPages; i++ ) {
                var $pager = $('<a href="javascript:void(0);" class="pager" '+pageAttribute+'="'+(i+1)+'"></a>');
                    $pager.html(i+1);

                    $pager.click(function(){
                        var page = $(this).eq(0).attr(pageAttribute);
                        goToPage(page);
                    });
                $pager.appendTo($isotopePager);
            }
        }
        $container.after($isotopePager);
    }();
}
// remove checks from all boxes and refilter
function clearAll(){
    $checkboxes.each(function (i, elem) {
        if (elem.checked) {
            elem.checked = null;
        }
    });
    currentFilter = '*';
    setPagination();
    goToPage(1);
}

setPagination();
goToPage(1);

//event handlers
$checkboxes.change(function(){
    var filter = $(this).attr(filterAttribute);
    currentFilter = filter;
    setPagination();
    goToPage(1);
});

$('#clear-filters').click(function(){clearAll()});
/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
    display: block;
}
body {
    line-height: 1;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}



.centered-component {
    width : 100%;
    max-width : 1300px;
    margin : 0 auto;
    display : flex;
    flex-wrap : wrap;
    padding : 100px 0;
}

.centered-component .filter-sidebar {
    width : 100%;
    max-width : 250px;
    margin-right : 24px;
}

.centered-component .content-block {
    flex : 1;
} 

.filter-sidebar {
    display : flex;
    flex-direction: column;
}

.products-container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap : 24px;
}

.isotope-container > h2{
    margin-bottom :48px;
}

.products-item {
    position: relative !important;
    top : initial !important;
    left : initial !important;
}

.products-container {
    height : initial !important;
}

.isotope-pager {
    margin-top : 42px;
}

.isotope-container + .isotope-container {
    margin-top : 64px;
}
<!doctype html>
<html>
<head>
    <title>Isotope</title>
    <link rel="stylesheet" href="style.css" />
</head>

<body>
<div class="centered-component">
    <div class="filter-sidebar">
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="beige" />
            beige
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="green" />
            green
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="blue" />
            blue
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="orange" />
            orange
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="purple" />
            purple
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="pink" />
            pink
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="teal" />
            teal
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="yellow" />
            yellow
        </label>
        <label class="filter-item">
            <input type="checkbox"  class="filter-checkbox" value="black" />
            black
        </label>


    </div>

    <div class="content-block">
        <div class="isotope-container">
            <h2 class="heading">Category 1</h2>
            
            <ul class="products-container">
                <li class="products-item beige">
                    <h2>beige</h2>
                </li>
                <li class="products-item green">
                    <h2>green</h2>
                </li>

                <li class="products-item blue">
                    <h2>blue</h2>
                </li>
                <li class="products-item orange">
                    <h2>orange</h2>
                </li>
                <li class="products-item purple">
                    <h2>purple</h2>
                </li>
                <li class="products-item pink">
                    <h2>pink</h2>
                </li>
                <li class="products-item teal">
                    <h2>teal</h2>
                </li>

                <li class="products-item yellow">
                    <h2>yellow</h2>
                </li>
                <li class="products-item black">
                    <h2>black</h2>
                </li>
                <li class="products-item beige">
                    <h2>beige</h2>
                </li>

            </ul>
        </div>

    </div>
    
</div>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.isotope/2.2.2/isotope.pkgd.min.js"></script>
<script src="filter.js"></script>


</body>
</html>

Related