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

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

ただいまの
回答率

87.37%

特定のクラスを持つselect option を全て非表示にしたい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 756

score 47

お世話になっております。
当方Laravel5.5にてWebSiteを構築しております、
環境はmac OS Mojave10.14.2
ブラウザはGoogle Chrome バージョン: 71.0.3578.98になります。

質問内容

下記のエラーが出現して困っています。
(特定のクラスを全てvisibleもしくはhiddenにしたいです)
どこが誤っていますでしょうか?

尚、エラーではクラス「visible_check」に関してエラーが出ていて、
このクラスはviewには1つしかありませんが、
この後

        document.getElementsByClassName("."+(i+1)"_"+old[i-1]).style.visibility ="visible";


の部分で、viewに複数箇所あるクラスに対してvisibleを設定しようと考えています。
(ループしている理由は、最下部背景の通り、階層のold値からvisible/hiddenを設定したいからです)
なので、タイトルは「特定のクラスを持つselect option を全て非表示にしたい」としております。

エラー内容

Uncaught TypeError: Cannot set property 'visibility' of undefined
if(old){
        var old_count_hierarchy = old.length;
        for( var i=1; i<=old_count_hierarchy; i++){

        //エラー箇所
        document.getElementsByClassName('.visible_check').style.visibility ="hidden";

        document.getElementsByClassName("."+(i+1)"_"+old[i-1]).style.visibility ="visible";
        document.getElementById('hierarchy_'+i+'_block').style.display ="block";

          }
        ;}

;}

view

            <select name='category_path[]' class='list {{$filterSelect}}' {{$target}} id={{$hierarchy}} {{$empty}}>
              @foreach($items->category_hierarchized[$key1] as $key2 => $val2)
              @if(old('category_path') === null)
              <?php $selected = ""; ?>
              @else`
              //old値に基づいてoptionにselectedをつける
              @if(array_search($items->category_hierarchized[$key1][$key2]['category_id'],old('category_path')) !== false)
              <?php $selected = "selected"; ?>
              @else
              <?php $selected = ""; ?>
              @endif
              @endif


//hidden・visibleの制御をかけたい箇所
               <option class="visible_check {{$key1}}_{{$val2['data-belongsto']}}" value="{{$items->category_hierarchized[$key1][$key2]['category_id']}}"
                 data-reference="{{$items->category_hierarchized[$key1][$key2]['category_id']}}"
                 data-belongsto="{{$val2['data-belongsto']}}"
                 onclick="visible_handling({{$key1}},{{$items->category_hierarchized[$key1][$key2]['category_id']}})" {{$disabled}} {{$selected}}>


                 {{$items->category_hierarchized[$key1][$key2]['category_name']}}
               </option>
              @endforeach
            </select>

以下、本件の背景です。

実装しているもの

・今実装している画面には全選択肢が全て見えているセレクトボックスが5つあります。
・セレクトボックスはcascadingで、第一階層のセレクトボックスを選択すると、
それに合わせて第二階層のセレクトボックスとその内容が出現し、選択できるというようになっています。
・各セレクトボックスはview側でforeachを回して全て選択肢やセレクトボックスを用意しています。

<セレクトボックスの出現制御>
javascriptによるdisplay制御で、見える見えないの制御をしています。
(例えば、第一階層までしか選択していない時は、display制御で第三階層を見せていない
だけで、view側にはある)

<選択肢の出現制御>
・セレクトボックスの選択肢(option)のvalueには一意の番号が振ってあります
・各セレクトボックスの選択肢(option)は、親の番号を持っているので、
最初の階層で選択された選択肢の番号に応じて、次の階層で選択肢を変更します

<参考>
下記のデモは構築中のものと非常に似ていて、
3階層が常に見えていますが、
1階層目を選択すると2階層目が見えて…のようになる違いがあります。
(選択肢の見え方・制御は同じです)
https://www.jqueryscript.net/demo/jQuery-Plugin-To-Create-Dependent-Select-Boxes-Filter-Select/

やりたいこと

この上で、入力画面から次の画面に
行き、戻るボタンから戻ってきた際に、
optionのold値にある値から、
入力画面で入力したときと同じように画面を
再現すべく、当質問に至りました。

宜しくお願い致します。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+2

getElementsByClassNameは配列のようなオブジェクトが返ってくるので、全部処理するならループするなどしないといけません。

【Document.getElementsByClassName() - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/Document/getElementsByClassName

【getElementsByClassNameとgetElementByIdの返り値の違い - Qiita】
https://qiita.com/rindarinda5/items/c26dc81fe8cd98992dc1

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/03/25 16:03

    kei344様
    ご回答ありがとうございます。
    ご提示のQiitaを参考に下記の様にjavascriptを書き換えたのですが、
    Uncaught TypeError: Cannot read property 'visibility' of undefined
    とエラーが発生してしまいました。
    「 document.getElementsByClassName("."+(i+1)+"_"+old[i-1]).style.visibility」
    では要素のスタイルは取得できないでしょうか…?


    var redElement = document.getElementsByClassName("."+(i+1)+"_"+old[i-1]).style.visibility;
    console.log(redElement[0]);
    for (var k = 0; k < redElement.length; k++) {
    redElement[k] ="visible";
    }

    キャンセル

  • 2019/03/25 16:07 編集

    あまりJavaScriptを触ったことがないのでしょうか。
    入門書などをざっと読んでから作成されるほうが結局早く実装できると思いますよ。

    var redElement = document.getElementsByClassName((i+1)+"_"+old[i-1]);
    for (var k = 0; k < redElement.length; k++) {
    redElement[k].style.visibility ="visible";
    } // (追記:クラスセレクタが付いていた物を削除)

    キャンセル

  • 2019/03/26 21:02

    ご返信ありがとうございます。
    Laravelは数ヶ月触りましたが、
    jsはほぼノータッチ状態からこの状態になっており、
    時間の関係でサンプルを組み合わせて走り抜けたい事情があります。
    ご教示ありがとうございます。

    ご指摘の方法でエラーは解消いたしました。
    ありがとうございます。

    キャンセル

+1

単純なCSSなら

<style>
.old{display:none}
</style>
<form>
<select>
<option value="">---</option>
<option value="1" class="old">1</option>
<option value="2">2</option>
<option value="3" class="old">3</option>
<option value="4">4</option>
<option value="5" class="old">5</option>
</select>
</form>


chromeならこれで十分
ただしIEなどdisplayで調整ができないブラウザがあるので
対応したいならサーバーサイドもしくはjsでoptionを削ってしまってください

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/03/25 16:06 編集

    yambejp様、
    ご回答ありがとうございます。
    背景の方に記載させて頂きましたが、
    階層をループさせて表示しており、
    選択したoptionをoldで取得して、
    oldに入っているoption以外を非表示としたいので、
    javascriptで動的に処理必要があります。

    >IEなどdisplayで調整ができないブラウザがある
    こちら大変参考になりました、ありがとうございます。
    optionを削るというのは、具体的にどのような記述になりますでしょうか…?
    只今調べましたが、
    viewには全ての選択肢を保持するという前提では実装が難しそうです。

    キャンセル

  • 2019/03/25 16:17 編集

    jsで処理するなら命名規則に合致するclassを探してdisplay:noneにするか
    削除するかですね

    キャンセル

  • 2019/03/26 21:01

    ご返信ありがとうございます。
    display:noneで実装いたしました。

    IEでも使用想定がありますので、
    以降気をつけてまいります。

    キャンセル

0

これを参考にできますか?
value値を見て判断します

<!DOCTYPE html>
<meta charset="utf-8">
<title>?</title>

<body>

<select name="hoge1"></select>
<select name="hoge2"></select>
<select name="hoge3"></select>
<select name="hoge4"></select>
<select name="hoge5"></select>


<script>
//まずは初期設定
const
  A = (a, b)=> a.concat (C[0].map (a => b + '-' + a)),
  B = (a, b)=> ['', ...b].forEach (c => a.appendChild (new Option (c,c))),
  C = [[1,2,3,4,5]],
  D = [...document.querySelectorAll ('select[name^="hoge"]')];

C[1]=C[0].reduce (A, []);
C[2]=C[1].reduce (A, []);  
C[3]=C[2].reduce (A, []);  
C[4]=C[3].reduce (A, []);  

D.forEach ((e,i)=> B(e,C[i]));


//本題はここから

D.forEach (a => a.addEventListener ('change', ({target: e})=> {
  let n = D.indexOf (e);
  if (-1 < n)
    D.slice (n + 1).forEach (s => {
      let op = [...s.options];
      op.forEach ((a,i) => a.style.display = (a.value.indexOf (e.value) == 0 || i == 0) ? 'block': 'none');
      s.selectedIndex = 0;
    });

}, false));

</script>

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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