外部サービスやライブラリなしで、投稿一覧(ページ)にカテゴリー検索を実装する方法を紹介しています。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);
        }
    });
}コードの解説
JavaSctiptでは大きく分けて2つの処理を行なっています。
- 絞り込みのボタンが押された時の処理
- フィルタリングを行う関数を定義
それぞれについて簡単に解説していきます。
ボタンが押された時の処理
categoryLabels.forEach(function (item) {
    item.classList.remove(activeClass);
});全てのボタンから一旦、is-activeクラスを削除しています。
this.classList.add(activeClass);クリックされたボタンに、is-activeクラスを付与しています。search-list__itemにis-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クラスが付与されると、その投稿アイテムが非表示となります。
以上です。最後までお読みいただきありがとうございます。


