Вложенность optgroups в раскрывающемся списке / select
Я создал элемент управления customer c# 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>
однако, в приведенном выше примере фрагмента, это рендеринг, как если бы Level Two
был при том же количестве отступов, что и Level One
.
есть ли способ создать вложенное поведение optgroup, которое я ищу?
8 ответов
спецификация HTML здесь действительно сломана. Он должен разрешать вложенные optgroups и рекомендовать агентам пользователей отображать их как вложенные меню. Вместо допускается только один уровень optgroup. Тем не менее, они должны сказать следующее по этому вопросу:
Примечание. Реализаторам рекомендуется, что будущие версии HTML могут расширить механизм группировки, чтобы разрешить вложенные группы (т. е. элементы OPTGROUP могут гнездиться). Это позволит авторам представить более богатую иерархию выбор.
и пользовательские агенты могут начать использовать подменю для отображения optgoups вместо отображения заголовков перед первым элементом option в optgroup, как они это делают сейчас.
Это просто отлично, но если вы добавляете опцию witch не в optgroup, она становится багги.
<select>
<optgroup label="Level One">
<option> A.1 </option>
<optgroup label=" Level Two">
<option> 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>
Ok, если кто-нибудь когда-нибудь читает это: лучший вариант-добавить четыре
s на каждом дополнительном уровне отступа, казалось бы!
так:
<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>
<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>
Я думаю, если у вас есть что-то структурированное и сложное, вы можете рассмотреть что-то другое, чем один раскрывающийся список.
мне очень нравится решение сломанной стрелки выше в этом посте. Я только что улучшил / изменил его немного, чтобы то, что называлось ярлыками, можно было переключать и не рассматривать варианты. Я использовал небольшой кусок 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;
}
мне нужно чистое и легкое решение (так что нет jQuery и тому подобное), которое будет выглядеть точно так же, как обычный HTML, также будет продолжать работать, когда задан только простой HTML (так что javascript только улучшит его), и который позволит искать, начиная буквы (включая национальные буквы UTF-8), если это возможно, где он не добавляет дополнительный вес. Он также должен работать быстро в очень медленных браузерах (думаю, rPi - поэтому предпочтительно не javascript, выполняющийся после загрузки страницы).
в firefox он использует В CSS определить и, таким образом, разрешить поиск по буквам, а в других браузерах он будет использовать
добавляю (но там он не поддерживает быстрый поиск по буквам). В любом случае, я вполне доволен результатами.
вы можете попробуйте его в действии здесь
это звучит так:
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 " и т.д. обозначают уровень identation):
<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();
}
}
Я знаю, что это было довольно давно, однако у меня есть немного больше, чтобы добавить:
это невозможно в HTML5 или каких-либо предыдущих спецификациях, а также не предлагается в HTML5.1 пока. Я сделал запрос в public-html-comments
список рассылки, но мы посмотрим, что из этого выйдет.
независимо, в то время как это невозможно с помощью <select>
тем не менее, вы можете достичь аналогичного эффекта со следующим HTML, плюс некоторые CSS для prettiness:
<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, однако вы можете добавить некоторые, чтобы скрыть переключатели, а затем изменить цвет фона выбранный предмет или что-то в этом роде.
имейте в виду, что это далеко не идеальное решение, но если вам абсолютно нужен вложенный выбор с разумной кросс-браузерной совместимостью, это, вероятно, так близко, как вы собираетесь получить.