web-dev-qa-db-ja.com

ドロップダウンリスト/選択でのoptgroupのネスト

そのコンテンツがoptgroupsであることをレンダリングできるカスタマーc#DropDownListコントロールを作成しました(最初からではなく、インターネット上で見つかったコードを編集しましたが、何をしているのか正確に理解していますが)。

ただし、ドロップダウンに2つのレベルのインデントが必要な状況に遭遇しました。

<select>
  <optgroup label="Level One">
    <option> A.1 </option>
    <optgroup label="Level Two">
      <option> A.B.1 </option>
    </optgroup>
    <option> A.2 </option>
  </optgroup>
</select>

ただし、上記のサンプルスニペットでは、Level TwoLevel Oneと同じインデント量であるかのようにレンダリングされます。

私が探しているネストされたoptgroup動作を生成する方法はありますか?

73
Ed James

わかりました。誰かがこれを読んだことがあるなら、最良の選択肢は4つの&nbsp;sインデントの各余分なレベルで、それは思われるでしょう!

そう:

<select>
 <optgroup label="Level One">
  <option> A.1 </option>
  <optgroup label="&nbsp;&nbsp;&nbsp;&nbsp;Level Two">
   <option>&nbsp;&nbsp;&nbsp;&nbsp; A.B.1 </option>
  </optgroup>
  <option> A.2 </option>
 </optgroup>
</select>
40
Ed James

ここのHTML仕様は本当に壊れています。ネストされたoptgroupを許可し、ユーザーエージェントがネストされたメニューとしてレンダリングすることを推奨する必要があります。代わりに、 1つのoptgroupレベルのみが許可されます 。しかし、彼らはこの件に関して次のことを言わなければなりません:

注意。実装者は、HTMLの将来のバージョンがグループ化メカニズムを拡張して、ネストされたグループを許可する可能性がある(つまり、OPTGROUP要素がネストされる可能性がある)ことをお勧めします。これにより、著者は選択肢のより豊富な階層を表すことができます。

また、ユーザーエージェントは、現在のようにoptgroupの最初のoption要素の前にタイトルを表示する代わりに、サブメニューを使用してoptgoupsをレンダリングすることができます。

61

これは問題ありませんが、optgroupにないオプションを追加するとバグが発生します。

<select>
  <optgroup label="Level One">
    <option> A.1 </option>
    <optgroup label="&nbsp;&nbsp;&nbsp;&nbsp;Level Two">
      <option>&nbsp;&nbsp;&nbsp;&nbsp; A.B.1 </option>
    </optgroup>
    <option> A.2 </option>
  </optgroup>
  <option> A </option>
</select>

Cssを使用してoptgroupをすぐに閉じると、はるかに改善されます。

<select>
  <optgroup label="Level One"></optgroup>
  <option style="padding-left:15px"> A.1 </option>
  <optgroup label="Level Two" style="padding-left:15px"></optgroup>
  <option style="padding-left:30px"> A.B.1 </option>
  <option style="padding-left:15px"> A.2 </option>
  <option> A </option>
</select>
47
Adam
<style>
    .NestedSelect{display: inline-block; height: 100px; border: 1px Black solid; overflow-y: scroll;}
    .NestedSelect label{display: block; cursor: pointer;}
    .NestedSelect label:hover{background-color: #0092ff; color: White;}
    .NestedSelect input[type="radio"]{display: none;}
    .NestedSelect input[type="radio"] + span{display: block; padding-left: 0px; padding-right: 5px;}
    .NestedSelect input[type="radio"]:checked + span{background-color: Black; color: White;}
    .NestedSelect div{margin-left: 15px; border-left: 1px Black solid;}
    .NestedSelect label > span:before{content: '- ';}
</style>

<div class="NestedSelect">
    <label><input type="radio" name="MySelectInputName"><span>Fruit</span></label>
    <div>
        <label><input type="radio" name="MySelectInputName"><span>Apple</span></label>
        <label><input type="radio" name="MySelectInputName"><span>Banana</span></label>
        <label><input type="radio" name="MySelectInputName"><span>Orange</span></label>
    </div>

    <label><input type="radio" name="MySelectInputName"><span>Drink</span></label>
    <div>
        <label><input type="radio" name="MySelectInputName"><span>Water</span></label>

        <label><input type="radio" name="MySelectInputName"><span>Soft</span></label>
        <div>
            <label><input type="radio" name="MySelectInputName"><span>Cola</span></label>
            <label><input type="radio" name="MySelectInputName"><span>Soda</span></label>
            <label><input type="radio" name="MySelectInputName"><span>Lemonade</span></label>
        </div>

        <label><input type="radio" name="MySelectInputName"><span>Hard</span></label>
        <div>
            <label><input type="radio" name="MySelectInputName"><span>Bear</span></label>
            <label><input type="radio" name="MySelectInputName"><span>Whisky</span></label>
            <label><input type="radio" name="MySelectInputName"><span>Vodka</span></label>
            <label><input type="radio" name="MySelectInputName"><span>Gin</span></label>
        </div>
    </div>
</div>
8
Broken Arrow

この投稿の上記の Broken Arrowのソリューション が本当に気に入っています。ラベルと呼ばれるものを切り替えることができ、オプションと見なされないように、少し改善/変更しました。私は小さなjQueryを使用しましたが、これはjQueryなしで実行できます。

中間ラベル(リーフラベルなし)を、クリック時に関数を呼び出すリンクに置き換えました。この関数は、クリックされたリンクの次のdivを切り替えて、オプションを展開または折りたたみます。これにより、通常は望ましいものである、階層内の中間要素を選択する可能性が回避されます。中間要素を選択できるバリアントを作成するのは簡単です。

これは修正されたhtmlです。

<div class="NestedSelect">
    <a onclick="toggleDiv(this)">Fruit</a>
    <div>
        <label>
            <input type="radio" name="MySelectInputName"><span>Apple</span></label>
        <label>
            <input type="radio" name="MySelectInputName"><span>Banana</span></label>
        <label>
            <input type="radio" name="MySelectInputName"><span>Orange</span></label>
    </div>

    <a onclick="toggleDiv(this)">Drink</a>
    <div>
        <label>
            <input type="radio" name="MySelectInputName"><span>Water</span></label>

        <a onclick="toggleDiv(this)">Soft</a>
        <div>
            <label>
                <input type="radio" name="MySelectInputName"><span>Cola</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Soda</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Lemonade</span></label>
        </div>

        <a onclick="toggleDiv(this)">Hard</a>
        <div>
            <label>
                <input type="radio" name="MySelectInputName"><span>Bear</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Whisky</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Vodka</span></label>
            <label>
                <input type="radio" name="MySelectInputName"><span>Gin</span></label>
        </div>
    </div>
</div>

小さなJavaScript/jQuery関数:

function toggleDiv(element) {
    $(element).next('div').toggle('medium');
}

そして、CSS:

.NestedSelect {
    display: inline-block;
    height: 100%;
    border: 1px Black solid;
    overflow-y: scroll;
}

.NestedSelect a:hover, .NestedSelect span:hover  {
    background-color: #0092ff;
    color: White;
    cursor: pointer;
}

.NestedSelect input[type="radio"] {
    display: none;
}

.NestedSelect input[type="radio"] + span {
    display: block;
    padding-left: 0px;
    padding-right: 5px;
}

.NestedSelect input[type="radio"]:checked + span {
    background-color: Black;
    color: White;
}

.NestedSelect div {
    display: none;
    margin-left: 15px;
    border-left: 1px black
    solid;
}

.NestedSelect label > span:before, .NestedSelect a:before{
    content: '- ';
}

.NestedSelect a {
    display: block;
}

JSFiddleでのサンプルの実行

5
TrilceAC

構造化された複雑なものがある場合は、単一のドロップダウンボックス以外のものを検討するかもしれません。

5
Matthew Groves

プレーンHTMLとまったく同じように見えるクリーンで軽量なソリューションが必要でした(jQueryなどはありません)。プレーンHTMLのみがプリセットされている場合も動作し続けるため(javascriptが拡張するだけです)、開始文字で検索できます(各国のUTF-8文字を含む)可能な場合は、余分な重みを追加しません。また、非常に遅いブラウザで高速に動作する必要があります(rPiを考えてください-ページの読み込み後にjavascriptが実行されないことが望ましい)。

Firefoxでは、CSS識別を使用して文字による検索を許可し、他のブラウザーでは&nbsp;を先頭に追加します(ただし、文字によるクイック検索はサポートしていません)。とにかく、私は結果に非常に満足しています。

ここで実際に試してみてください

こんなふうになります:

CSS:

.i0 { }
.i1 { margin-left: 1em; }
.i2 { margin-left: 2em; }
.i3 { margin-left: 3em; }
.i4 { margin-left: 4em; }
.i5 { margin-left: 5em; }

HTML(クラス「i1」、「i2」などは識別レベルを示します):

<form action="/filter/" method="get">
<select name="gdje" id="gdje">
<option value=1 class="i0">Svugdje</option>
<option value=177 class="i1">Bosna i Hercegovina</option>
<option value=190 class="i2">Babin Do</option>  
<option value=258 class="i2">Banja Luka</option>
<option value=181 class="i2">Tuzla</option>
<option value=307 class="i1">Crna Gora</option>
<option value=308 class="i2">Podgorica</option>
<option value=2 SELECTED class="i1">Hrvatska</option>
<option value=5 class="i2">Bjelovarsko-bilogorska županija</option>
<option value=147 class="i3">Bjelovar</option>
<option value=79 class="i3">Daruvar</option>  
<option value=94 class="i3">Garešnica</option>
<option value=329 class="i3">Grubišno Polje</option>
<option value=368 class="i3">Čazma</option>
<option value=6 class="i2">Brodsko-posavska županija</option>
<option value=342 class="i3">Gornji Bogićevci</option>
<option value=158 class="i3">Klakar</option>
<option value=140 class="i3">Nova Gradiška</option>
</select>
</form>

<script>
<!--
        window.onload = loadFilter;
// -->   
</script>

JavaScript:

function loadFilter() {
  'use strict';
  // indents all options depending on "i" CSS class
  function add_nbsp() {
    var opt = document.getElementsByTagName("option");
    for (var i = 0; i < opt.length; i++) {
      if (opt[i].className[0] === 'i') {
      opt[i].innerHTML = Array(3*opt[i].className[1]+1).join("&nbsp;") + opt[i].innerHTML;      // this means "&nbsp;" x (3*$indent)
      }
    }
  }
  // detects browser
  navigator.sayswho= (function() {
    var ua= navigator.userAgent, tem,
    M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*([\d\.]+)/i) || [];
    if(/trident/i.test(M[1])){
        tem=  /\brv[ :]+(\d+(\.\d+)?)/g.exec(ua) || [];
        return 'IE '+(tem[1] || '');
    }
    M= M[2]? [M[1], M[2]]:[navigator.appName, navigator.appVersion, '-?'];
    if((tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1];
    return M.join(' ');
  })();
  // quick detection if browser is firefox
  function isFirefox() {
    var ua= navigator.userAgent,
    M= ua.match(/firefox\//i);  
    return M;
  }
  // indented select options support for non-firefox browsers
  if (!isFirefox()) {
    add_nbsp();
  }
}  
3
Matija Nalis

これはかなり前のことでしたが、少し追加する必要があります。

これは、HTML5または以前の仕様では不可能であり、HTML5.1ではまだ提案されていません。 public-html-commentsメーリングリストにリクエストしましたが、何かが来るかどうかを確認します。

とにかく、<select>を使用してこれを行うことはまだできませんが、次のHTMLとかわいらしさのためのCSSで同様の効果を実現できます。

<ul>
  <li>
        <input type="radio" name="location" value="0" id="loc_0" />
        <label for="loc_0">United States</label>
        <ul>
          <li>
                Northeast
        <ul>
              <li>
                        <input type="radio" name="location" value="1" id="loc_1" />
                        <label for="loc_1">New Hampshire</label>
                  </li>
          <li>
                        <input type="radio" name="location" value="2" id="loc_2" />
                        <label for="loc_2">Vermont</label>
                  </li>
          <li>
                         <input type="radio" name="location" value="3" id="loc_3" />
                         <label for="loc_3">Maine</label>
                  </li>
                 </ul>
           </li>
       <li>
                   Southeast
           <ul>
                         <li>
                                <input type="radio" name="location" value="4" id="loc_4" />
                                <label for="loc_4">Georgia</label>
                         </li>
             <li>
                                <input type="radio" name="location" value="5" id="loc_5" />
                                <label for="loc_5">Alabama</label>
                         </li>
                   </ul>
                </li>
          </ul>
    </li>
    <li>
           <input type="radio" name="location" value="6" id="loc_6" />
           <label for="loc_6">Canada</label>
       <ul>
                  <li>
                         <input type="radio" name="location" value="7" id="loc_7" />
                         <label for="loc_7">Ontario</label>
                  </li>
          <li>
                          <input type="radio" name="location" value="8" id="loc_8" />
                      <label for="loc_8">Quebec</label>
                  </li>
          <li>
                           <input type="radio" name="location" value="9" id="loc_9" />
                           <label for="loc_9">Manitoba</label>
                  </li>
                </ul>
         </li>
  </ul>

さらに追加の利点として、これは<optgroups>自体の選択を許可できることも意味します。これは、たとえば、ネストされたカテゴリがあり、カテゴリが非常に詳細になり、ユーザーが階層の上位を選択できるようにする場合に便利です。

これはすべてJavaScriptなしでも機能しますが、ラジオボタンを非表示にし、選択したアイテムまたは何かの背景色を変更するためにいくつかを追加することができます。

これは完璧なソリューションとはほど遠いことを念頭に置いてください。ただし、適切なクロスブラウザー互換性を備えたネストされた選択が絶対に必要な場合、これはおそらくあなたが得ようとしているものに近いでしょう。

3