jQueryでフィルタ処理を作ってみよう
こんにちは、せんせーです。
検索、フィルタ、ソートなど、コンテンツが多いページで必要な情報にすばやくアクセスしてもらうための手法はいくつかありますが、最近お客様からのご要望が多いなと感じるのがフィルタ(絞り込み)処理です。
要求には検索ってあるけど実際の要件はこれフィルタだよね、ということもままあります。
そこで今日は簡易的なフィルタ処理を組んでみたいと思います。
もっとも、いい感じにフィルタ、ソートが実装できるプラグインはいくらでもあるので勉強目的でなければそういうのを使った方が早いですが、なんらかの他のシステムが動いている場合にちょろっと実装できると助かることがあるので、考え方だけでも承知しておいて損はないんじゃないでしょうか。
要求には検索ってあるけど実際の要件はこれフィルタだよね、ということもままあります。
そこで今日は簡易的なフィルタ処理を組んでみたいと思います。
もっとも、いい感じにフィルタ、ソートが実装できるプラグインはいくらでもあるので勉強目的でなければそういうのを使った方が早いですが、なんらかの他のシステムが動いている場合にちょろっと実装できると助かることがあるので、考え方だけでも承知しておいて損はないんじゃないでしょうか。
実装要件
- チェックボックスで選んだカテゴリの商品だけを表示したい
- 表示するものがなければ代替の文言を表示したい
- 表示されている件数を表示したい
こんな感じでいきたいと思います。よくありそうなパターンですね。
HTML
さっそくやってみましょう。
こんなHTMLを想定します。
このHTMLを眺めつつ、もう少し詳しくやりたい処理を言語化してみます。
どことどこの値が対応しているか、対応させるべきかというところを注意するといいんじゃないでしょうか。
上記を満たせたら完成ということですね。
こんなHTMLを想定します。
HTML
<form class="js-filter-form list_checkbox">
<label><input type="checkbox" name="filter" value="animal" checked> 動物</label>
<label><input type="checkbox" name="filter" value="onigiri" checked> おにぎり</label>
<label><input type="checkbox" name="filter" value="vegi" checked> 野菜</label>
<label><input type="checkbox" name="filter" value="space" checked> 宇宙</label>
<label><input type="checkbox" name="filter" value="cthulhu" checked> クトゥルフ</label>
</form>
<p class="js-filter-status text_status"><span>1件</span>のアイテムが該当します</p>
<ul class="js-filter-items flex-wrap">
<li data-cat="animal"><img src="monkey.png" alt="">フサオマキザル</li>
<li data-cat="vegi"><img src="yakiimo.png" alt="">お芋</li>
<li data-cat="animal"><img src="nutria.png" alt="">ヌートリア</li>
<li data-cat="onigiri"><img src="tenmusu.png" alt="">天むす</li>
<li data-cat="vegi"><img src="sayaendou.png" alt="">サヤエンドウ</li>
<li data-cat="space"><img src="sputnik.png" alt="">スプートニク1号</li>
<li data-cat="vegi"><img src="radish.png" alt="">ラディッシュ</li>
<li data-cat="space"><img src="ufo.png" alt="">キャトルミューティレーション</li>
<li data-cat="cthulhu"><img src="mi-go.png" alt="">ミ=ゴ</li>
<li data-cat="animal"><img src="serval.png" alt="">サーバル</li>
<li data-cat="space"><img src="moon.png" alt="">お月さま</li>
<li data-cat="onigiri"><img src="ume.png" alt="">うめぼし</li>
</ul>
どことどこの値が対応しているか、対応させるべきかというところを注意するといいんじゃないでしょうか。
- フォーム(.js-filter-form)内のチェックボックスがクリックされた時
- チェックされているvalueと等しいdata-cat値をもつ要素をリスト(.js-filter-items)から探し、表示状態にする
- 2に該当しない要素を非表示にする
- 表示状態の要素数を取得し、ステータス(.js-filter-status)に反映する
- 表示状態の要素数が0ならステータスの文言を変更する
上記を満たせたら完成ということですね。
チェックボックスをクリックした時に、チェックされている値を取得する
とりあえずフォーム内のチェックボックスがクリックされた時に、checkedになっている要素のvalueを取得して配列にいれてみます。
console.log()でログに出してみて、正常に取れていることを確認しておきます。
大丈夫そうなので、次にアイテムリストを順に調べていって、data-catの値が上で取得した配列の中にあるかどうかをチェックします。
配列内にdata-catの値がなかった場合はhiddenクラスを付与し、値があればhiddenクラスを外します。
表示のON/OFFはスタイルシートで制御します。
js
$(".js-filter-form :checkbox").on("click", function(){
var checked = [];
$(".js-filter-form :checked").each(function(){
checked.push($(this).val()); // pushは配列に値を追加します
});
console.log(checked);
});
js
$(".js-filter-form :checkbox").on("click", function(){
var checked = [];
$(".js-filter-form :checked").each(function(){
checked.push($(this).val()); // pushは配列に値を追加します
});
console.log(checked);
$(".js-filter-items li").each(function(){
var cat = $(this).data("cat");
var is_exist = $.inArray( cat, checked ); // inArray()は配列内に値があるかどうかを調べます
if (is_exist != -1) {
$(this).removeClass("hidden");
} else {
$(this).addClass("hidden");
}
})
});
表示のON/OFFはスタイルシートで制御します。
何件表示されているかをチェックする
あとはフィルタした結果何件になったか、0件だったらテキストを変化させるといった処理をいれて完成です。
要素数を数える方法もいくつかありますが、今回は単純に条件に合致した時にカウントアップするようにしました。
1度もカウントされなければ0件なので、その場合のテキストも設定します。
これで完成ですね。
フィルタ・ソート系のプラグインは見た目も面白く、色々な設定できるものが多いです。
が、設定がめんどくさかったりカスタマイズが難しかったりするので、要件がシンプルであれば自前で実装してしまったほうが後々メンテも楽だったり…どっちがいいかはケースバイケースですが、作れる選択肢はあった方が、まあいいですよねということで。
js
$(".js-filter-form :checkbox").on("click", function(){
var checked = [];
$(".js-filter-form :checked").each(function(){
checked.push($(this).val()); // push()は配列に値を追加します
});
console.log(checked);
var count = 0;
$(".js-filter-items li").each(function(){
var cat = $(this).data("cat");
var is_exist = $.inArray( cat, checked ); // inArray()は配列内に値があるかどうかを調べます
if (is_exist != -1) {
$(this).removeClass("hidden");
count++;
} else {
$(this).addClass("hidden");
}
});
if (count) {
var str = "<span>" + count + "件</span>のアイテムが該当します";
} else {
var str = "該当するアイテムはありません";
}
$(".js-filter-status").html(str);
});
1度もカウントされなければ0件なので、その場合のテキストも設定します。
これで完成ですね。
フィルタ・ソート系のプラグインは見た目も面白く、色々な設定できるものが多いです。
が、設定がめんどくさかったりカスタマイズが難しかったりするので、要件がシンプルであれば自前で実装してしまったほうが後々メンテも楽だったり…どっちがいいかはケースバイケースですが、作れる選択肢はあった方が、まあいいですよねということで。
DEMO
チェックボックスで表示カテゴリを絞り込むサンプルです。
1件のアイテムが該当します
- フサオマキザル
- お芋
- ヌートリア
- 天むす
- サヤエンドウ
- スプートニク1号
- ラディッシュ
- キャトルミューティレーション
- ミ=ゴ
- サーバル
- お月さま
- うめぼし