JavaScriptで実装する投稿一覧のカテゴリー検索【リスト表示を絞り込み】

JavaScriptのみで実装する投稿一覧のカテゴリー絞り込み機能

外部サービスやライブラリなしで、投稿一覧(ページ)にカテゴリー検索を実装する方法を紹介しています。jQueryも使用せず、素のJavaScriptだけのシンプルな実装方法です。

お知らせ等のブログの更新がほとんどなく、CMSをあえて入れないことがありますが、そのような時に特に有効です。

目次

JavaScriptでカテゴリー検索を実装した例

今回実装したのはこちらです。

ボタンをクリックすると、それぞれのカテゴリーの記事が絞り込まれます。アクティブなカテゴリーのボタンには、下線が付くようにしています。

用意したファイルは以下の通りです。

ファイル一式
  • index.html
  • style.css
  • script.js

コードの見本

以下がコードの見本です。コピペしていただくとそのまま使えると思います。

index.html

<!-- カテゴリー絞り込みのボタン -->
<div class="search-list">
    <button class="search-list__item js-category-label is-active" data-category="">すべて</button>
    <button class="search-list__item js-category-label" data-category="news">お知らせ</button>
    <button class="search-list__item js-category-label" data-category="column">コラム</button>
    <button class="search-list__item js-category-label" data-category="other">その他</button>
</div>
<!-- カテゴリー絞り込みのボタンここまで -->

<!-- 記事リスト -->
<ul class="entry-list">
    <li class="entry-list__item js-category-item" data-category="news">
        <div class="entry-list__meta">
            <span>2023/09/06</span>
            <span>お知らせ</span>
        </div>
        <a href="#" class="entry-list__title">この記事はお知らせです。この記事はお知らせです。この記事はお知らせです。</a>
    </li>
    <li class="entry-list__item js-category-item" data-category="column">
        <div class="entry-list__meta">
            <span>2023/09/06</span>
            <span>コラム</span>
        </div>
        <a href="#" class="entry-list__title">この記事はコラムです。この記事はコラムです。この記事はコラムです。</a>
    </li>
    <li class="entry-list__item js-category-item" data-category="other">
        <div class="entry-list__meta">
            <span>2023/09/06</span>
            <span>その他</span>
        </div>
        <a href="#" class="entry-list__title">この記事はその他です。この記事はその他です。この記事はその他です。</a>
    </li>
</ul>
<!-- 記事リストここまで -->

style.css

.search-list__item {
  appearance: none;
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
  color: inherit;
  background-color: #ddd;
  border-radius: initial;
  border: none;
  display: inline-block;
  padding: 10px;
  cursor: pointer;
}

.search-list__item.is-active {
  text-decoration: underline;
}

.entry-list {
  margin-top: 2em;
}

.entry-list__item+.entry-list__item {
  margin-top: 1em;
}

.entry-list__item.is-hide {
  display: none;
}

script.js

const categoryLabel = '.js-category-label';
const categoryItem = '.js-category-item';
const hideClass = 'is-hide';
const activeClass = 'is-active';

document.addEventListener('DOMContentLoaded', function () {
    const categoryLabels = document.querySelectorAll(categoryLabel);
    // 絞り込みを変更した時
    categoryLabels.forEach(function (item) {
        item.addEventListener('click', function () {
            categoryLabels.forEach(function (item) {
                item.classList.remove(activeClass);
            });
            this.classList.add(activeClass);
            const category = this.dataset.category;
            search_filter(category);
        });
    });
});

function search_filter(category) {
    const categoryItems = document.querySelectorAll(categoryItem);
    // 非表示状態を解除
    categoryItems.forEach(function (item) {
        item.classList.remove(hideClass);
    });
    // 値が空の場合はすべて表示
    if (category === '') {
        return;
    }
    // リスト内の各アイテムをチェック
    categoryItems.forEach(function (item) {
        const itemData = item.dataset.category;
        // 絞り込み対象かどうかを調べる
        if (itemData !== category) {
            item.classList.add(hideClass);
        }
    });
}

WAI-ARIAによるスクリーンリーダーへは対応していません。実務では必要に応じて、スクリーンリーダーへの対応を強化するため正しくWAI-ARIAを設定しましょう。

コードの解説

JavaSctiptでは大きく分けて2つの処理を行なっています。

JavaScriptの処理
  • 絞り込みのボタンが押された時の処理
  • フィルタリングを行う関数を定義

それぞれについて簡単に解説していきます。

ボタンが押された時の処理

categoryLabels.forEach(function (item) {
    item.classList.remove(activeClass);
});

全てのボタンから一旦、is-activeクラスを削除しています。

this.classList.add(activeClass);

クリックされたボタンに、is-activeクラスを付与しています。search-list__itemis-activeが付くと、下線が表示されます。

const category = this.dataset.category;
search_filter(category);

クリックされたボタンのdata-category属性を変数に格納し、その変数を引数としてsearch_filter関数を実行しています。

フィルタリングを行う関数の処理を定義

categoryItems.forEach(function (item) {
    item.classList.remove(hideClass);
});

全ての投稿アイテムから一旦、is-hideクラスを削除しています。

if (category === '') {
    return;
}

引数で渡ってきたcategoryの値が空の場合はすべての投稿アイテムを表示しています。

categoryItems.forEach(function (item) {
    const itemData = item.dataset.category;
    if (itemData !== category) {
        item.classList.add(hideClass);
    }
});

すべての投稿アイテムのdata-category属性と、引数で渡ってきたdata-category属性(クリックされたボタンが持つdata-category属性)が同一かどうかを判定しています。

同一でない場合:その投稿アイテムにis-hideクラスを付与
同一の場合:何も処理を行わない

.entry-list__item.is-hide {
  display: none;
}

投稿アイテムにis-hideクラスが付与されると、その投稿アイテムが非表示となります。

以上です。最後までお読みいただきありがとうございます。

目次