Вложения опций в выпадающем списке/select
Я создал элемент управления С# DropDownList клиента, который может отображать его содержимое, являются optgroups (не с нуля, я редактировал какой-то код, найденный в Интернете, хотя я точно понимаю, что он делает), и он отлично работает.
Однако теперь я столкнулся с ситуацией, когда мне нужно иметь два уровня отступов в моем выпадающем меню, т.е.
<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>
Однако, насколько мне известно, это будет выглядеть как обычные optgroups.
Есть ли способ создать это вложенное поведение?
Ответы
Ответ 1
Хорошо, если кто-нибудь еще прочтет это: лучший вариант - добавить четыре
на каждый дополнительный уровень отступов, казалось бы!
так:
<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>
Ответ 2
Спецификация HTML здесь действительно сломана. Он должен позволять вложенным группам пользователей и рекомендовать пользовательские агенты отображать их как вложенные меню. Вместо этого разрешен только один уровень группы opt.
Однако они должны сказать следующее по этому вопросу:
Примечание. Разработчикам рекомендуется, чтобы будущие версии HTML могли расширить механизм группировки, чтобы разрешить вложенные группы (т.е. Элементы OPTGROUP могут входить). Это позволит авторам представлять более богатую иерархию вариантов.
И пользовательские агенты могут начать использовать подменю для рендеринга optgoups вместо отображения титров перед первым элементом элемента в optgroup, как сейчас.
Ответ 3
Это просто отлично, но если вы добавите опцию, ведьма не в 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 и close 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>
Ответ 4
<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>
Ответ 5
Я думаю, что если у вас есть что-то структурированное и сложное, вы можете рассмотреть что-то другое, кроме одного раскрывающегося списка.
Ответ 6
Я знаю, что это было довольно давно, однако у меня есть немного дополнительного, чтобы добавить:
Это невозможно в 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, однако вы можете добавить некоторые, чтобы скрыть радиокнопки, а затем изменить цвет фона выбранного элемента или что-то в этом роде.
Помните, что это далеко не идеальное решение, но если вам абсолютно необходим вложенный выбор с разумной совместимостью между браузерами, это, вероятно, так близко, как вы собираетесь получить.
Ответ 7
Мне нужно было чистое и легкое решение (так что не jQuery и так далее), которое будет выглядеть точно так же, как обычный HTML, также будет продолжать работать, когда будет установлен только простой HTML (поэтому javascript только улучшит его), что позволит начиная с букв (включая национальные буквы UTF-8), если это возможно, где он не добавляет лишнего веса. Он также должен работать быстро в очень медленных браузерах (подумайте, что rPi - поэтому желательно, чтобы javascript не выполнялся после загрузки страницы).
В firefox он использует идентификатор CSS и, таким образом, позволяет выполнять поиск по буквам, а в других браузерах он будет использовать
prepending (но там он не поддерживает быстрый поиск по буквам). Во всяком случае, я доволен результатами.
Вы можете попробовать его в действии здесь
Это происходит следующим образом:
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(" ") + opt[i].innerHTML; // this means " " 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();
}
}
Ответ 8
Мне действительно нравится Broken Arrow solution выше в этом сообщении. Я только немного улучшил/изменил его, так что так называемые метки можно переключать и не считаться опциями. Я использовал небольшой кусок 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