如何在 isotope JS 中组合多个过滤器?

问题描述 投票:0回答:1

我有两个内容类型区域,其中包含独特的过滤器选项。这些是:

  1. type
  2. tag

我正在尝试利用 isotope.js 来实现双重过滤布局,但它总是给予最后单击的过滤器优先级。

请参阅此处的用例(参考下面的演示):

  1. 如果我点击“博客和新闻”,我应该看到两个帖子(作品)
  2. 如果我也单击“PDF”,那么我应该看不到任何帖子(因为不存在将 pdf 作为类的博客文章)。相反,它向我展示了包含 pdf 类的案例研究帖子。
  3. 如果我随后也单击“文章”,它应该再次显示没有帖子,因为不存在具有
    blog-and-news pdf article
    类的帖子。但相反,我向我展示了带有它的案例研究帖子。

组合过滤器不起作用。

文档说

arrange()
方法可以处理多个过滤器实例,但它在我的用例中不起作用。

我还尝试使用

concatValues()
函数来连接值(如许多演示中所示),但它仍然无法产生正确的结果。

在此处查看交互式演示

document.addEventListener('DOMContentLoaded', function() {

  var container = document.querySelector('.grid');
  var gridItems = container.querySelectorAll('.grid-item');
  const optionLinks = document.querySelectorAll('.rSidebar__options-li');

  var iso = new Isotope(container, {
    itemSelector: '.resourceCard',
    layoutMode: 'fitRows',
    transitionDuration: '0.5s',
  });

  var filters = {};

  function concatValues( obj ) {
    var value = '';
    for ( var prop in obj ) {
      value += obj[ prop ];
    }
    return value;
  }

  function handleFilterClick(event, filters, iso) {
    var listItem = event.target;
    var filterGroup = listItem.closest('.rSidebar__options').getAttribute('data-filter-group');
    var filterValue = listItem.getAttribute('data-filter');

    if (filters[filterGroup] === filterValue) {
      delete filters[filterGroup];
    } else {
      filters[filterGroup] = filterValue;
    }

    // Combine filters
    var filterValues = Object.values(filters).join(', ');
    // var filterValues = concatValues( filters );


    // debugging
    console.log('List Item:', listItem);
    console.log('Filter Group:', filterGroup);
    console.log('Filter Value:', filterValue);
    console.log('Filters Object:', filters);
    console.log('Filter Values:', filterValues);

    iso.arrange({ filter: filterValues });
  }

  optionLinks.forEach(function(optionLink) {
    optionLink.addEventListener('click', function(event) {
      event.preventDefault();
      this.classList.toggle('selected');
      handleFilterClick(event, filters, iso);
    });
  });


});
.post {
  padding: 100px;
}

.rSidebar__box {
  margin-bottom: 30px;
}
.rSidebar__options {
  padding-left: 0;
}
.rSidebar__options-li {
  margin-bottom: 17px;
  display: flex;
  align-items: center;
  cursor: pointer;
  width: fit-content;
}
.rSidebar__options-li.selected .rSidebar__options-square {
  background-color: #185A7D;
}
.rSidebar__options-square {
  height: 20px;
  width: 20px;
  transition: all 0.5s ease;
  border: 2px solid #000000;
}
.rSidebar__options-label {
  margin-left: 10px;
}

.grid {
  display: flex;
  flex-wrap: wrap;
  margin: -14px 0 0 -14px;
}
.grid-item {
  box-sizing: border-box;
  width: calc(33.33% - 14px);
  margin: 14px 0 18px 14px;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.min.js"></script>


<div class="post">
  <div class="container">
    <div class="row justify-content-between">

      <!-- SIDEBAR -->
      <div class="col-3">
        <div class="rSidebar">

          <!-- tags -->
          <div class="rSidebar__box">
            <span class="rSidebar__label d-block fw-bold">Filter by tag</span>
            <ul class="rSidebar__options button-group" data-filter-group="type">
              <li class="rSidebar__options-li" data-filter=".pdf">
                <span class="rSidebar__options-square"></span>
                <span class="rSidebar__options-label d-block buttonTemp" data-filter=".pdf">PDF</span>
              </li>
                <li class="rSidebar__options-li" data-filter=".article">
                <span class="rSidebar__options-square"></span>
                <span class="rSidebar__options-label d-block buttonTemp" data-filter=".article">Article</span>
              </li>
            </ul>
          </div>

          <!--  type -->
          <div class="rSidebar__box">
            <span class="rSidebar__label d-block fw-bold">Filter by type</span>
            <ul class="rSidebar__options button-group" data-filter-group="type">
              <li class="rSidebar__options-li" data-filter=".blogs-and-news">
                <span class="rSidebar__options-square"></span>
                <span class="rSidebar__options-label d-block buttonTemp" data-filter=".blogs-and-news">Blog & News</span>
              </li>
                <li class="rSidebar__options-li" data-filter=".case-study">
                <span class="rSidebar__options-square"></span>
                <span class="rSidebar__options-label d-block buttonTemp" data-filter=".case-study">Case Studies</span>
              </li>
            </ul>
          </div>
          <!-- end -->
        </div>
      </div>
      <!-- END -->

      <!-- GRID -->
      <div class="col-7">
        <div class="grid">
          <article class="resourceCard grid-item case-study pdf"><span class="resourceCard__body-title">Case study, PDF post</span></article>
          <article class="resourceCard grid-item blogs-and-news"><span class="resourceCard__body-title">Blogs and news post</span></article>
          <article class="resourceCard grid-item blogs-and-news article"><span class="resourceCard__body-title">Blogs and news, article post</span></article>
        </div>
      </div>
      <!-- END -->

    </div>
  </div>
</div>

最新尝试

document.addEventListener('DOMContentLoaded', function() {

  var container = document.querySelector('.grid');
  var gridItems = container.querySelectorAll('.grid-item');
  const optionLinks = document.querySelectorAll('.rSidebar__options-li');

  var iso = new Isotope(container, {
    itemSelector: '.resourceCard',
    layoutMode: 'fitRows',
    transitionDuration: '0.5s',
  });

  var filters = {};

  function concatValues( obj ) {
    var value = '';
    for ( var prop in obj ) {
      value += obj[ prop ];
    }
    return value;
  }

  function handleFilterClick(event, filters, iso) {
    var listItem = event.target;
    var filterGroup = listItem.closest('.rSidebar__options').getAttribute('data-filter-group');
    var filterValue = listItem.getAttribute('data-filter');

    var allowMultiple = listItem.closest('.rSidebar__options').getAttribute('data-multiple') === 'true';

    if (allowMultiple) {
      // toggle the filter value
      if (filters[filterGroup] && filters[filterGroup].includes(filterValue)) {
        // remove the filter value if it already exists
        filters[filterGroup] = filters[filterGroup].filter(value => value !== filterValue);
      } else {
        // add the filter value if it doesn't exist
        if (!filters[filterGroup]) {
          filters[filterGroup] = [];
        }
        filters[filterGroup].push(filterValue);
      }
    } else {
      // replace the filter value
      filters[filterGroup] = [filterValue];
    }

    var filterValues = concatValues( filters );

    // console.log('List Item:', listItem);
    // console.log('Filter Group:', filterGroup);
    // console.log('Filter Value:', filterValue);
    // console.log('Filters Object:', filters);
    // console.log('Filter Values:', filterValues);

    iso.arrange({ filter: filterValues });

  }


  optionLinks.forEach(function(optionLink) {
    optionLink.addEventListener('click', function(event) {
      event.preventDefault();
      this.classList.toggle('selected');
      handleFilterClick(event, filters, iso);
    });
  });


});

javascript html jquery css jquery-isotope
1个回答
0
投票

您需要更新每当单击标记/类型并选择值时创建的对象值,然后使用更新后的数组传入过滤器。

在下面的代码中,我添加了条件,即:如果目标元素上有选定的类,则仅添加/更新数组的值(filters),否则只需从键中删除该data-filter值。

演示代码:

var filters = {};
var container = document.querySelector('.grid');
var gridItems = container.querySelectorAll('.grid-item');
const optionLinks = document.querySelectorAll('.rSidebar__options-li');

var iso = new Isotope(container, {
  itemSelector: '.resourceCard',
  layoutMode: 'fitRows',
  transitionDuration: '0.5s',
});

function concatValues(obj) {
  var value = '';
  for (var prop in obj) {
    value += obj[prop];
  }
  return value;
}

function handleFilterClick(event, filters) {
  console.clear()
  var listItem = event;
  var filterGroup = listItem.closest('.rSidebar__options').getAttribute('data-filter-group');
  var data_filter = listItem.getAttribute('data-filter');
  
  //if selected class present do below : 
  if (listItem.classList.contains('selected')) {
    if (filters[filterGroup] && !filters[filterGroup].includes(data_filter)) {
      filters[filterGroup] = filters[filterGroup] + data_filter; //update the key value
    } else {
      filters[filterGroup] = data_filter // add new value
    }
  } else {
    filters[filterGroup] = filters[filterGroup].replace(data_filter, '') //remove class as unselected
  }

  var filterValue = concatValues(filters);
  console.log(filterValue)

  iso.arrange({
    filter: filterValue
  });
}

optionLinks.forEach(function(optionLink) {
  optionLink.addEventListener('click', function(event) {
    event.preventDefault();
    this.classList.toggle('selected');
    handleFilterClick(this, filters);
  });
});
.post {
  padding: 100px;
}

.rSidebar__box {
  margin-bottom: 30px;
}

.rSidebar__options {
  padding-left: 0;
}

.rSidebar__options-li {
  margin-bottom: 17px;
  display: flex;
  align-items: center;
  cursor: pointer;
  width: fit-content;
}

.rSidebar__options-li.selected .rSidebar__options-square {
  background-color: #185A7D;
}

.rSidebar__options-square {
  height: 20px;
  width: 20px;
  transition: all 0.5s ease;
  border: 2px solid #000000;
}

.rSidebar__options-label {
  margin-left: 10px;
}

.grid {
  display: flex;
  flex-wrap: wrap;
  margin: -14px 0 0 -14px;
}

.grid-item {
  box-sizing: border-box;
  width: calc(33.33% - 14px);
  margin: 14px 0 18px 14px;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.min.js"></script>


<div class="post">
  <div class="container">
    <div class="row justify-content-between">

      <!-- SIDEBAR -->
      <div class="col-3">
        <div class="rSidebar">

          <!-- tags -->
          <div class="rSidebar__box">
            <span class="rSidebar__label d-block fw-bold">Filter by tag</span>
            <ul class="rSidebar__options button-group" data-filter-group="tag">
              <li class="rSidebar__options-li" data-filter=".pdf">
                <span class="rSidebar__options-square"></span>
                <span class="rSidebar__options-label d-block buttonTemp" data-filter=".pdf">PDF</span>
              </li>
              <li class="rSidebar__options-li" data-filter=".article">
                <span class="rSidebar__options-square"></span>
                <span class="rSidebar__options-label d-block buttonTemp" data-filter=".article">Article</span>
              </li>
            </ul>
          </div>

          <!--  type -->
          <div class="rSidebar__box">
            <span class="rSidebar__label d-block fw-bold">Filter by type</span>
            <ul class="rSidebar__options button-group" data-filter-group="type">
              <li class="rSidebar__options-li" data-filter=".blogs-and-news">
                <span class="rSidebar__options-square"></span>
                <span class="rSidebar__options-label d-block buttonTemp" data-filter=".blogs-and-news">Blog & News</span>
              </li>
              <li class="rSidebar__options-li" data-filter=".case-study">
                <span class="rSidebar__options-square"></span>
                <span class="rSidebar__options-label d-block buttonTemp" data-filter=".case-study">Case Studies</span>
              </li>
            </ul>
          </div>
          <!-- end -->
        </div>
      </div>
      <!-- END -->

      <!-- GRID -->
      <div class="col-7">
        <div class="grid">
          <article class="resourceCard grid-item case-study pdf"><span class="resourceCard__body-title">Case study, PDF post</span></article>
          <article class="resourceCard grid-item blogs-and-news"><span class="resourceCard__body-title">Blogs and news post</span></article>
          <article class="resourceCard grid-item blogs-and-news article"><span class="resourceCard__body-title">Blogs and news, article post</span></article>
          <article class="resourceCard grid-item blogs-and-news article pdf case-study"><span class="resourceCard__body-title">Blogs and news,article,pdf,case study </span></article>
        </div>
      </div>
      <!-- END -->

    </div>
  </div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.