データ属性とJSで絞り込み(AND)検索

6

データ属性と JS で絞り込み検索作った

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./index.css" />
    <script src="./index.js"></script>
    <title>Document</title>
  </head>
  <body>
    <ul class="filters">
      <li>
        <button class="js-item-term" data-term="お菓子">お菓子</button>
      </li>
      <li>
        <button class="js-item-term" data-term=""></button>
      </li>
      <li>
        <button class="js-item-term" data-term="調味料">調味料</button>
      </li>
      <li>
        <button class="js-item-term" data-term="ANIMAL">ANIMAL</button>
      </li>
      <li>
        <button class="js-item-term" data-term=""></button>
      </li>
      <li>
        <button class="js-item-term" data-term="ニンニク">ニンニク</button>
      </li>
      <li>
        <button class="js-item-term" data-term=""></button>
      </li>
      <li>
        <button class="js-item-term" data-term="野菜">野菜</button>
      </li>
      <li>
        <button class="js-item-term" data-term=""></button>
      </li>
      <li>
        <button class="js-item-term" data-term="お寿司">お寿司</button>
      </li>
      <li>
        <button class="js-item-term" data-term="嬉しい">嬉しい</button>
      </li>
    </ul>

    <ul class="products">
      <li class="js-item" data-tag="魚,お寿司,ANIMAL, 嬉しい">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">えんがわ握り</span>
          <ul class="products__box--tags">
            <li></li>
            <li>お寿司</li>
            <li>ANIMAL</li>
            <li>嬉しい</li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="野菜">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">もやし</span>
          <ul class="products__box--tags">
            <li>野菜</li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="お菓子, 嬉しい">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">グミ</span>
          <ul class="products__box--tags">
            <li>お菓子</li>
            <li>嬉しい</li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="調味料">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title"></span>
          <ul class="products__box--tags">
            <li>調味料</li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="肉,ANIMAL, 嬉しい">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">焼肉</span>
          <ul class="products__box--tags">
            <li></li>
            <li>ANIMAL</li>
            <li>嬉しい</li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="酒, 嬉しい">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">スト缶</span>
          <ul class="products__box--tags">
            <li></li>
            <li>嬉しい</li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="酒, 嬉しい">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">ビール</span>
          <ul class="products__box--tags">
            <li></li>
            <li>嬉しい</li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="ニンニク, 嬉しい">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">ニンニク</span>
          <ul class="products__box--tags">
            <li>ニンニク</li>
            <li>嬉しい</li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="嬉しい">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">現金</span>
          <ul class="products__box--tags">
            <li>嬉しい</li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">お惣菜</span>
          <ul class="products__box--tags">
            <li></li>
          </ul>
        </div>
      </li>
      <li class="js-item" data-tag="肉, ANIMAL, 嬉しい">
        <div class="products__box">
          <img src="https://placehold.jp/150x100.png" alt="" />
          <span class="products__box--title">鶏皮ポン酢</span>
          <ul class="products__box--tags">
            <li></li>
            <li>ANIMAL</li>
            <li>嬉しい</li>
          </ul>
        </div>
      </li>
    </ul>
  </body>
</html>
// variables
$wrap: 560px;
$gapY: 20px;

// reset
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
ul {
  list-style: none;
}

// 共通
.filters,
.products {
  display: flex;
  flex-wrap: wrap;
  margin: $gapY auto 0;
  max-width: $wrap;
  width: 100%;
  & > li {
    margin: 10px;
  }
}

// ボタン
.filters {
  button {
    appearance: none;
    background: #4082f0;
    border: none;
    border-radius: 30px;
    box-shadow: 0 2px 8px -2px rgba(0, 0, 0, 0.59);
    color: #fff;
    cursor: pointer;
    font-size: 12px;
    line-height: 15px;
    min-width: 120px;
    padding: 1em;
    transform: translateY(-2px);
    transition: all 0.2s;
    &.active,
    &:hover {
      box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.79);
      transform: none;
    }
    &.active {
      background: #15366d;
    }
  }
}

// 商品部分
.products {
  border-top: 1px solid #f6f6f6;
  padding-top: 20px;
  & > li {
    width: calc((100% - (10px * 6)) / 3);
  }
  &__box {
    border: 1px solid #cacaca;
    display: flex;
    flex-direction: column;
    padding: 8px;
    &--title {
      color: #444;
      font-size: 0.9em;
      margin-top: 10px;
    }
    &--tags {
      font-size: 10px;
      li {
        color: #888;
        display: inline-block;
        &::before {
          color: #4082f0;
          content: "#";
          opacity: 0.5;
          padding-right: 2px;
        }
        &:not(:first-child) {
          margin-left: 6px;
        }
      }
    }
  }
}

// 表示/非表示
.js-item {
  animation: fadeInItem 0.5s both;
  will-change: opacity, width;
  &.fadeOut {
    animation: fadeOutItem 0.5s both;
    .products__box {
      display: none;
    }
  }
}

@keyframes fadeInItem {
  0% {
    margin: 0;
    opacity: 0;
    padding: 0;
    width: 0;
  }
  100% {
    opacity: 1;
  }
}

@keyframes fadeOutItem {
  0% {
    opacity: 1;
  }

  100% {
    display: none;
    margin: 0;
    opacity: 0;
    padding: 0;
    width: 0;
  }
}
"use strict";

window.addEventListener("load", function() {
  const d = document;

  const items = d.querySelectorAll(".js-item");

  const terms = [];

  const buttons = d.querySelectorAll(".js-item-term");
  for (const button of buttons) {
    button.addEventListener("click", function() {
      button.classList.toggle("active");

      // クリックした条件を絞り込み条件リストに追加/削除
      const term = button.getAttribute("data-term");
      const termPosition = terms.indexOf(term);
      if (termPosition !== -1) {
        terms.splice(termPosition, 1);
      } else {
        terms.push(term);
      }
      console.log("terms: ", terms);

      // 絞り込み
      for (const item of items) {
        // 選択されてる条件ないなら全てのfadeOut取って処理終了
        if (terms.length === 0 && item.classList.contains("fadeOut")) {
          item.classList.remove("fadeOut");
          continue;
        }
        // 空白削除して配列に
        const itemTagsArray = item
          .getAttribute("data-tag")
          .replace(/\s+/g, "")
          .split(",");
        const isIncludedTerm = terms.filter(function(term) {
          return itemTagsArray.indexOf(term) !== -1;
        });
        if (isIncludedTerm.length !== terms.length && !item.classList.contains("fadeOut")) {
          // 現在の条件と完全一致してなくてfadeOutクラスもなければfadeOutクラス付与
          item.classList.add("fadeOut");
        } else if (isIncludedTerm.length === terms.length && item.classList.contains("fadeOut")) {
          // 現在の条件と完全一致しててfadeOutクラスあるならfadeOutクラス外す
          item.classList.remove("fadeOut");
        }
      }
    });
  }
});
  • SNSでシェアしよう
  • Twitterでシェア
  • FaceBookでシェア
  • Lineでシェア
  • 記事タイトルとURLをコピー
トップへ戻るボタン

\ HOME /

トップへ戻る