複数条件による絞り込み検索

ECサイトの商品一覧ページ等でお馴染みの、絞り込み検索機能をjQueryを用いて構築してみます。
▼実装するサイトの想定
パソコンECサイト内のノートPC一覧ページ
▼絞り込み条件
①液晶の種類：フルHD液晶・4K液晶・4K有機EL液晶
②画面サイズ：13インチ・15インチ・17インチ
▼絞り込み検索に用いるユーザーインターフェース
・ラジオボタン＝液晶の種類
・チェックボックス＝画面サイズ

ラジオボタンとチェックボックスもディフォルト表示ままではなく、疑似要素を用いてカスタマイズをしていきます。
##HTML
まずはユーザーが絞り込み条件にチェックを入れる、ラジオボタンとチェックボックスを構築します。全選択ボタンもあった方がユーザー的に都合が良いと思うので実装します。
name・value・data-categoryに記述する値が絞り込み条件の要となります。

```html
<div class="wrapper">
    <h1>複数条件での絞り込み検索 実装例</h1>
    <!-- 絞込み検索UI start -->
    <div class="search_area">
      <form id="selectForm">
        <div class="search_ui category_search_box">
          <label class="checkbox_margin">
            <input type="radio" name="category" value="fullHD" class="radio_input">
            <span class="radio_parts padding_adjust1">フルHD</span></label>
          <label class="checkbox_margin">
            <input type="radio" name="category" value="4K" class="radio_input">
            <span class="radio_parts padding_adjust1">4K</span></label>
          <label class="checkbox_margin">
            <input type="radio" name="category" value="orgEL" class="radio_input">
            <span class="radio_parts padding_adjust1">4K有機EL</span></label>
          <label class="checkbox_margin">
            <input type="radio" name="category" value="" checked="checked" class="radio_input" id="allItem">
            <span class="radio_parts padding_adjust1">全てのノートPC</span></label>
        </div>
        <div class="search_ui size_search_box pc"> <span id="sizeBox">
            <label>
              <input type="checkbox" name="size" value="13inch" class="checkbox_input size_sort">
              <span class="checkbox_parts">13インチ</span></label>
            <label>
              <input type="checkbox" name="size" value="15inch" class="checkbox_input size_sort">
              <span class="checkbox_parts">15インチ</span></label>
            <label>
              <input type="checkbox" name="size" value="17inch" class="checkbox_input size_sort">
              <span class="checkbox_parts">17インチ</span></label>
          </span>
          <label class="all_btn">
            <input type="checkbox" id="checkAll" name="size_all" class="checkbox_input">
            <span class="checkbox_parts">全サイズ選択</span></label>
        </div>
      </form>
    </div>
    <!-- 絞込み検索UI end -->
　　<!-- 絞り込み対象一覧 start -->
    <div class="item_container list">
      <div class="item" data-category='["fullHD"]' data-size="13inch">
        <p class="item_name">13インチ フルHD液晶 ノートPC</p>
        <img src="" alt="対象製品画像" />
      </div>
      <div class="item" data-category='["fullHD"]' data-size="15inch">
        <p class="item_name">15インチ フルHD液晶 ノートPC</p>
        <img src="" alt="対象製品画像" />
      </div>
      <div class="item" data-category='["4K"]' data-size="15inch">
        <p class="item_name">15インチ 4K液晶 ノートPC</p>
        <img src="" alt="対象製品画像" />
      </div>
      <div class="item" data-category='["4K", "orgEL"]' data-size="15inch">
        <p class="item_name">15インチ 4K有機EL液晶 ノートPC</p>
        <img src="" alt="対象製品画像" />
      </div>
      <div class="item" data-category='["4K"]' data-size="17inch">
        <p class="item_name">17インチ 4K液晶 ノートPC</p>
        <img src="" alt="対象製品画像" />
      </div>
      <div class="item" data-category='["4K", "orgEL"]' data-size="17inch">
        <p class="item_name">17インチ 4K有機EL液晶 ノートPC</p>
        <img src="" alt="対象製品画像" />
      </div>
    </div>
    <!-- 絞り込み対象一覧 end -->
```
##CSS
続いてラジオボタンとチェックボックスをカスタマイズしていきます。
まずはディフォルトのボタン類を非表示にし、疑似要素を用いてオリジナルを構築していきます。
最後の「絞り込み条件外のアイテム」については、jQueryの記述に関係しています。

```css
/* ラジオボタンの装飾 */
.radio_input {
    display: none;
}

.radio_parts {
    padding-left: 25px;
    position: relative;
    margin-right: 20px;
}

.radio_parts::before {
    content: "";
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 18px;
    height: 18px;
    border: 1px solid #999;
    border-radius: 50%;
}

.radio_input:checked+.radio_parts::after {
    content: "";
    display: block;
    position: absolute;
    top: 4px;
    left: 4px;
    width: 12px;
    height: 12px;
    background: #0050c1;
    border-radius: 50%;
}

/* チェックボックスの装飾 */
.checkbox_input {
    display: none;
}

.checkbox_parts {
    padding-left: 25px;
    position: relative;
    margin-right: 25px;
}

.checkbox_parts::before {
    content: "";
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 18px;
    height: 18px;
    border: 1px solid #999;
}

.checkbox_input:checked+.checkbox_parts::after {
    content: "";
    display: block;
    position: absolute;
    top: -5px;
    left: 5px;
    width: 7px;
    height: 14px;
    transform: rotate(40deg);
    border-bottom: 3px solid #0050c1;
    border-right: 3px solid #0050c1;
}

/*他エリア*/
.wrapper {
    width: 1000px;
    margin: 30px auto;
}

h1{
    text-align: center;
    font-size: 1.7rem;
    font-weight: 500;
    margin-bottom: 30px;
    color: #0050c1;
}

.search_area {
    text-align: center;
}

.search_area div {
    margin-bottom: 10px;
}

.item_container {
    display: flex;
    flex-wrap: wrap;
}

.item {
    margin: 1.0rem;
    padding: 1.0rem;
    background: #efefef;
    width: calc(80% / 3);
    text-align: center;
}
/*絞り込み条件外のアイテム*/
.hide_item {
    display: none;
}
```
##JavaScript（jQuery）
ラジオボタンやチェックボックスの入力された絞り込み条件を取得し、各商品が持つnameやvalueの値を参照して、対象であれば表示、対象外であれば非表示にする仕様です。
※head内等でjQueryは読み込んでいる前提。

```javascript
let searchUi = ".search_ui"; // 絞り込み検索条件設定エリア
let listItem = ".item"; // 検索対象アイテム
let hideItem = "hide_item"; // 対象外アイテムに付与されるclass名
let checkBox = 'input[name="size"]'; //チェックボックスのnameを指定

// 絞り込み条件の変更
$(function () {
  $(document).on("change", searchUi + " input", function () {
    search_filter();
  });
});

function search_filter() {
  // 非表示状態を解除
  $(listItem).removeClass(hideItem);
  for (let i = 0; i < $(searchUi).length; i++) {
    let name = $(searchUi).eq(i).find("input").attr("name");
    // チェックされた検索条件を取得
    let searchData = get_selected_input_items(name);
    // チェック項目無し or 全てを選択している場合
    if (searchData.length === 0 || searchData[0] === "") {
      continue;
    }
    // リスト内の各アイテムをチェック
    for (let j = 0; j < $(listItem).length; j++) {
      // アイテムに設定している項目を取得
      let itemData = get_setting_values_in_item($(listItem).eq(j), name);
      // 絞り込み対象かどうかを調べる
      let check = array_match_check(itemData, searchData);
      if (!check) {
        $(listItem).eq(j).addClass(hideItem);
      }
    }
  }
}

// チェックの入った値の一覧を取得する
function get_selected_input_items(name) {
  let searchData = [];
  $("[name=" + name + "]:checked").each(function () {
    searchData.push($(this).val());
  });
  return searchData;
}

// リスト内のアイテムに設定している値の一覧を取得する
function get_setting_values_in_item(target, data) {
  let itemData = target.data(data);
  if (!Array.isArray(itemData)) {
    itemData = [itemData];
  }
  return itemData;
}

// 2つの配列内で一致する文字列があるかどうかを調べる
function array_match_check(arr1, arr2) {
  // 絞り込み対象かどうかを調べる
  let arrCheck = false;
  for (let i = 0; i < arr1.length; i++) {
    if (arr2.indexOf(arr1[i]) >= 0) {
      arrCheck = true;
      break;
    }
  }
  return arrCheck;
}

// 全サイズ選択解除
$(function () {
  $("#checkAll").on("click", function () {
    $(".size_sort").prop("checked", this.checked);
  });
  $(".size_sort").on("click", function () {
    if ($("#sizeBox :checked").length == $("#sizeBox :input").length) {
      $("#checkAll").prop("checked", "checked");
    } else {
      $("#checkAll").prop("checked", false);
    }
  });
});
```
仕組みが理解しやすいようシンプルな条件で構築してみましたが、条件追加などのカスタマイズもしやすいかと思います。
また、ラジオボタンやチェックボックスを操作しやすい大きさにしたり、サイトの雰囲気やトンマナに合わせてデザインすることも重要ですね。