質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.48%

複数カテゴリ絞り込みを実装したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,890

score 46

前提・実現したいこと

お世話になります。宜しくお願い致します。

リストを複数の項目で絞り込みを行いたいと思い、あるサイトを参考にjQueryで実装致しました。
サイトで紹介されていました通りの動きは出来たのですが、下記2点が実現出来なく困っております。

1.別項目選択でも同じ内容を表示したい
項目1の「ホテル」を選択した場合、【ホテルハワイ・ハワイアンレストラン】【五十嵐ホテル】【やどや】が結果として表示され、「レストラン」を選択した場合【海鮮レストラン】「観光地」を選択した場合【水族館】が表示されます。
【ホテルハワイ・ハワイアンレストラン】にはレストランも含まれている為、「ホテル」未選択で「レストラン」を選択した場合も【ホテルハワイ・ハワイアンレストラン】が表示されるようにしたいです。
また、【ホテルハワイ・ハワイアンレストラン】のようなパターンは今後増える予定です。

2.項目未選択時は全リスト非表示
各項目が未選択の場合、選択結果表示部は非表示で項目からなにか選択された時点で選択結果表示部に表示するようにしたいです。

参考にしたサイトです
https://spreadsheep.net/search_by_javascript/

該当のソースコード

<div class="js_conditions" data-type="type">
    <div>項目1</div>
    <div>
        <ul>
            <li><input id="type-hotel" type="checkbox" name="type" value="hotel"><label for="type-hotel">ホテル</label></li>
            <li><input id="type-restaurant" type="checkbox" name="type" value="restaurant"><label for="type-restaurant">レストラン</label></li>
            <li><input id="type-spot" type="checkbox" name="type" value="spot"><label for="type-spot">観光地</label></li>
        </ul>
    </div>
</div>

<div class="js_conditions" data-type="object">
    <div>項目2</div>
    <div>
        <ul>
            <li><input id="object-resort" type="checkbox" name="object" value="resort"><label for="object-resort">リゾートホテル</label></li>
            <li><input id="object-hiclass" type="checkbox" name="object" value="hiclass"><label for="object-hiclass">高級ホテル</label></li>
            <li><input id="object-guesthouse" type="checkbox" name="object" value="guesthouse"><label for="object-guesthouse">民宿</label></li>
        </ul>
    </div>
</div>

<div class="js_conditions" data-type="period">
    <div>項目3</div>
    <div>
        <ul>
            <li><input id="period-100" type="checkbox" name="period" value="100"><label for="period-100">100</label></li>
            <li><input id="period-200" type="checkbox" name="period" value="200"><label for="period-200">200</label></li>
            <li><input id="period-300" type="checkbox" name="period" value="300"><label for="period-300">300</label></li>
        </ul>

    </div>
</div>






<div>
    <ul>
        <li class="js_target" data-type="hotel" data-object="resort" data-period="200">ホテルハワイ・ハワイアンレストラン</li>
        <li class="js_target" data-type="hotel" data-object="hiclass" data-period="300">五十嵐ホテル</li>
        <li class="js_target" data-type="hotel" data-object="hotel" data-period="100">やどや</li>
        <li class="js_target" data-type="restaurant" data-object="resort" data-period="200">海鮮レストラン</li>
        <li class="js_target" data-type="spot" data-object="hiclass" data-period="300">水族館</li>
    </ul>

</div>
input {
    display: none;
}
.js_target{
  display: none;
}
.js_target.js_selected{
  display: block;
}
.tab-btnbox > div:nth-of-type(2) ul li {
    display: inline-block;
    border: 1px solid #494949;
    font-size: 16px;
    margin: 0 5px 10px 0;
}
.tab-btnbox > div:nth-of-type(2) ul li label {
    display: block;
    width: 100%;
    text-align: center;
    padding: 10px 20px;
    cursor: pointer;
}
$(function(){
  var box = $('.js_target');//検索対象のDOMを格納する
  var conditions = $('.js_conditions');//現在の条件の選択状況を保持するオブジェクト
  var findConditions;//各data-typeの小要素(input)を格納する
  var currentType;//現在のdata-typeを示す
  var count = 0;//検索ヒット数
  var checkcount = 0;//各data-typeのチェックボックス選択数
  var data_check = 0;//対象項目のデータがどれだけチェック状態と一致しているか

  var condition ={};//チェックボックスの入力状態を保持するオブジェクト

  $('.js_denominator').text(box.length);//件数表示の分母をセット

  for(var i = 0; i < conditions.length; i++){//ターゲットのdata-typeを参照し、メソッドとしてconditionに個別に代入する
    currentType = conditions[i].getAttribute('data-type');
    condition[currentType] = [];
  }

  function setConditions(){//条件設定

    count = 0;
    box.removeClass('js_selected');

    for(var i = 0; i < conditions.length; i++){//data-typeごとの処理

      currentType = conditions[i].getAttribute('data-type');

      findConditions = conditions[i].querySelectorAll('input');

      for(var n = 0; n< findConditions.length; n++){//inputごとの処理

        if(findConditions[n].checked){//現在選択中のインプットが選択されている場合
          condition[currentType][findConditions[n].value] = true;
          checkcount++
        } else {
          condition[currentType][findConditions[n].value] = false;
        }
        if(findConditions.length === n+1){//ループが最後の場合
          if(checkcount === 0){
            for(var t = 0; t < findConditions.length; t++){
              condition[currentType][findConditions[t].value] = true;
            }
          }
          checkcount = 0;
        }
      }
    }


    for(var m = 0, len = box.length; m< len; ++m){//最初に取得したターゲットの情報と、現在のinputの選択状態を比較して処理を行う

      for(var i = 0; i < conditions.length; i++){//ターゲットのdata-typeを参照し、メソッドとしてconditionに個別に代入する
        currentType = conditions[i].getAttribute('data-type');

        if(condition[currentType][$(box[m]).data(currentType)]){
          data_check++;
        } else {

        }
      }

        if(data_check === conditions.length){
          count++;
          $(box[m]).addClass('js_selected');
        }else{

        }
        data_check = 0;

    }


    $('.js_numerator').text(count);//件数表示の分子をセット
  }

  setConditions();

  $(document).on('click','input',function(){

    setConditions();

  });

  $(document).on('click','.js_release',function(){

    $('.bl_selectBlock_check input').attr("checked", false);

    setConditions();

  });


});

試したこと

1つの項目選択で複数表示させる為にリスト部分のdata-typeにスペースを開けて複数記載してみましたが、反応しませんでした。
data-type="hotel restaurant"のようにしましたが、「hotel」「restaurant」どちらも反応しなくなりました。
jQueryも何度も見たのですが、どこでどう選択した項目が反応しているのか勉強不足の為検討も付きませんでした。

2つめの項目未選択時選択結果非表示についてですが、CSSで出来ないかと考えてみましたが、
クラス「.js_selected」のJS側での制御がどのようになっているのか、なんとなくでしか理解出来なかった為コードを触る事が出来ませんでした。

jQueryの勉強不足、理解不足な為ほぼ手を付けれずまた具体的な説明が出来ず大変申し訳ございませんが、皆様のお知恵をお借りしたいと存じます。
宜しくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

AとかBとかソースに書かれていないので命題が意味不明です

とりあえず項目1を選ぶことでリストを表示・非表示する仕組みです
あと、なにをどうしたいのか明示してください

<script>
$(function(){
  $('.js_target').hide();
  $('[name=type]').on('change',function(){
    var types=$('[name=type]:checked').map(function(){
      return $(this).val();
    }).get();
    $('.js_target').hide().filter(function(){
      return $.inArray($(this).data('type'),types)>=0;
    }).show();
  });
});
</script>
<div class="js_conditions" data-type="type">
    <div>項目1</div>
    <div>
        <ul>
            <li><input id="type-hoge" type="checkbox" name="type" value="hoge"><label for="type-hoge">項目1の選択1</label></li>
            <li><input id="type-rest" type="checkbox" name="type" value="rest"><label for="type-rest">項目1の選択2</label></li>
        </ul>
    </div>
</div>
<div class="js_conditions" data-type="object">
    <div>項目2</div>
    <div>
        <ul>
            <li><input id="object-one" type="checkbox" name="object" value="one"><label for="object-one">項目2の選択1</label></li>
            <li><input id="object-two" type="checkbox" name="object" value="two"><label for="object-two">項目2の選択2</label></li>
            <li><input id="object-three" type="checkbox" name="object" value="three"><label for="object-three">項目2の選択3</label></li>
        </ul>
    </div>
</div>
<div class="js_conditions" data-type="period">
    <div>項目3</div>
    <div>
        <ul>
            <li><input id="period-100" type="checkbox" name="period" value="100"><label for="period-100">100</label></li>
            <li><input id="period-200" type="checkbox" name="period" value="200"><label for="period-200">200</label></li>
            <li><input id="period-300" type="checkbox" name="period" value="300"><label for="period-300">300</label></li>
        </ul>

    </div>
</div>
<div>
    <ul>
        <li class="js_target" data-type="rest" data-object="one" data-period="100">リスト1</li>
        <li class="js_target" data-type="hoge" data-object="two" data-period="200">リスト2</li>
        <li class="js_target" data-type="rest" data-object="three" data-period="300">リスト3</li>
    </ul>

</div>

追記

なんとなく理解した内容を反映
カスタムデータに複数データを持つ方法

data-type='["hotel","restaurant"]'
data-type='["hotel"]'


のようにしてください。
ただし、他のタグがdata-typeを1種しか持たなくても配列形式にしてください

<script>
$(function(){
  $('.js_target').hide();
  var choice=function(me){
    var types=$('[name=type]:checked').map(function(){
      return $(this).val();
    }).get();
    $('.js_target').hide().filter(function(){
      return $(this).data('type').some(function(x){
        return $.inArray(x,types)>=0;
      });
    }).show();
  }
  $('[name=type],[name=object]').on('change',choice);
});
</script>

<div class="js_conditions" data-type="type">
    <div>項目1</div>
    <div>
        <ul>
            <li><input id="type-hotel" type="checkbox" name="type" value="hotel"><label for="type-hotel">ホテル</label></li>
            <li><input id="type-restaurant" type="checkbox" name="type" value="restaurant"><label for="type-restaurant">レストラン</label></li>
            <li><input id="type-spot" type="checkbox" name="type" value="spot"><label for="type-spot">観光地</label></li>
        </ul>
    </div>
</div>

<div class="js_conditions" data-type="object">
    <div>項目2</div>
    <div>
        <ul>
            <li><input id="object-resort" type="checkbox" name="object" value="resort"><label for="object-resort">リゾートホテル</label></li>
            <li><input id="object-hiclass" type="checkbox" name="object" value="hiclass"><label for="object-hiclass">高級ホテル</label></li>
            <li><input id="object-guesthouse" type="checkbox" name="object" value="guesthouse"><label for="object-guesthouse">民宿</label></li>
        </ul>
    </div>
</div>

<div class="js_conditions" data-type="period">
    <div>項目3</div>
    <div>
        <ul>
            <li><input id="period-100" type="checkbox" name="period" value="100"><label for="period-100">100</label></li>
            <li><input id="period-200" type="checkbox" name="period" value="200"><label for="period-200">200</label></li>
            <li><input id="period-300" type="checkbox" name="period" value="300"><label for="period-300">300</label></li>
        </ul>

    </div>
</div>
<div>
    <ul>
        <li class="js_target" data-type='["hotel","restaurant"]' data-object="resort"   data-period="200">ホテルハワイ・ハワイアンレストラン</li>
        <li class="js_target" data-type='["hotel"]'              data-object="hiclass"  data-period="300">五十嵐ホテル</li>
        <li class="js_target" data-type='["hotel"]'              data-object="hotel"    data-period="100">やどや</li>
        <li class="js_target" data-type='["restaurant"]'         data-object="resort"   data-period="200">海鮮レストラン</li>
        <li class="js_target" data-type='["spot"]'               data-object="hiclass"  data-period="300">水族館</li>
    </ul>

</div>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/05 13:19

    ご回答頂きありがとうございます。

    ご質問の仕方が悪く大変失礼致しました。
    実現したいことをHTMLに沿ってのご説明になるように訂正致しましたので、大変お手数でございますが再度ご教示頂けますでしょうか。

    宜しくお願い致します。

    キャンセル

  • 2019/02/05 14:12 編集

    各項目の中ではor検索、項目同士はand検索ということでよろしいですか?
    カスタムdataに配列をもたせる方法を追記してあります

    キャンセル

  • 2019/02/05 17:44

    ありがとうございます。

    各項目内はor検索でお間違い御座いませんが、項目同士でもor検索となります。
    作成頂きましたソース確認させて頂きました。項目1の選択結果希望の動きが確認出来ました。
    ありがとうございます。
    項目2と項目3もソースを確認しながら作成してみたいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る