Html 在下拉列表/选择中嵌套选项组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1037732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Nesting optgroups in a dropdownlist/select
提问by Ed James
I have created a customer c# DropDownList control that can render out it's contents are optgroups (Not from scratch, I edited some code found on the internet, although I do understand exactly what it's doing), and it works fine.
我创建了一个客户 c# DropDownList 控件,它可以渲染出它的内容是 optgroups(不是从头开始,我编辑了一些在互联网上找到的代码,尽管我确实了解它在做什么),并且它工作正常。
However, I have now come across a situation where I need to have two levels of indentation in my dropdown, i.e.
但是,我现在遇到了一种情况,我需要在下拉菜单中有两级缩进,即
<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>
However, in the example snippet above, it is rendering as if Level Two
was at the same amount of indentation as Level One
.
但是,在上面的示例代码段中,它呈现Level Two
的缩进量与Level One
.
Is there a way to produce the nested optgroup behavior I am looking for?
有没有办法产生我正在寻找的嵌套 optgroup 行为?
采纳答案by Ed James
Ok, if anyone ever reads this: the best option is to add four
s at each extra level of indentation, it would seem!
好吧,如果有人读过这个:最好的选择是
在每个额外的缩进级别添加四个s,看起来!
so:
所以:
<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>
回答by Raphael Schweikert
The HTML spec here is really broken. It should allow nested optgroups and recommend user agents render them as nested menus. Instead, only one optgroup level is allowed. However, they do have to say the following on the subject:
这里的 HTML 规范真的很糟糕。它应该允许嵌套 optgroups 并建议用户代理将它们呈现为嵌套菜单。相反,只允许一个 optgroup 级别。但是,他们确实必须就该主题说以下内容:
Note. Implementors are advised that future versions of HTML may extend the grouping mechanism to allow for nested groups (i.e., OPTGROUP elements may nest). This will allow authors to represent a richer hierarchy of choices.
笔记。建议实现者,未来版本的 HTML 可能会扩展分组机制以允许嵌套组(即 OPTGROUP 元素可以嵌套)。这将允许作者代表更丰富的选择层次。
And user agents could start using submenus to render optgoups instead of displaying titles before the first option element in an optgroup as they do now.
用户代理可以开始使用子菜单来呈现 optgoups,而不是像现在那样在 optgroup 中的第一个选项元素之前显示标题。
回答by Adam
This is just fine but if you add option which is not in optgroup it gets buggy.
这很好,但是如果您添加不在 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>
Would be much better if you used css and close optgroup right away :
如果您使用 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>
回答by Broken Arrow
<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>
回答by TrilceAC
I really like the Broken Arrow's solutionabove in this post. I have just improved/changed it a bit so that what was called labels can be toggled and are not considered options. I have used a small piece of jQuery, but this could be done without jQuery.
我真的很喜欢这篇文章中上面的断箭解决方案。我刚刚对其进行了一些改进/更改,以便可以切换所谓的标签并且不被视为选项。我使用了一小部分 jQuery,但是这可以在没有 jQuery 的情况下完成。
I have replaced intermediate labels (no leaf labels) with links, which call a function on click. This function is in charge of toggling the next div of the clicked link, so that it expands/collapses the options. This avoids the possibility of selecting an intermediate element in the hierarchy, which usually is something desired. Making a variant that allows to select intermediate elements should be easy.
我已经用链接替换了中间标签(没有叶子标签),点击调用函数。此函数负责切换单击链接的下一个 div,以便展开/折叠选项。这避免了在层次结构中选择中间元素的可能性,这通常是需要的。制作允许选择中间元素的变体应该很容易。
This is the modified html:
这是修改后的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>
A small javascript/jQuery function:
一个小的 javascript/jQuery 函数:
function toggleDiv(element) {
$(element).next('div').toggle('medium');
}
And the css:
和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;
}
回答by Matthew Groves
I think if you have something that structured and complex, you might consider something other than a single drop-down box.
我认为如果您有结构化和复杂的内容,您可能会考虑除单个下拉框之外的其他内容。
回答by James Billingham
I know this was quite a while ago, however I have a little extra to add:
我知道这是很久以前的事了,但是我还有一点要补充:
This is not possible in HTML5 or any previous specs, nor is it proposed in HTML5.1 yet. I have made a request to the public-html-comments
mailing list, but we'll see if anything comes of it.
这在 HTML5 或任何以前的规范中是不可能的,在 HTML5.1 中也没有提出。我已向public-html-comments
邮件列表提出请求,但我们会看看是否有任何结果。
Regardless, whilst this is not possible using <select>
yet, you can achieve a similar effect with the following HTML, plus some CSS for prettiness:
无论如何,虽然目前还无法使用,<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>
As an extra added benefit, this also means you can allow selection of the <optgroups>
themselves. This might be useful if you had, for example, nested categories where the categories go into heavy detail and you want to allow users to select higher up in the hierarchy.
作为额外的好处,这也意味着您可以允许选择<optgroups>
它们自己。例如,如果您有嵌套类别,其中类别包含大量细节,并且您希望允许用户在层次结构中选择更高的位置,则这可能很有用。
This will all work without JavaScript, however you might wish to add some to hide the radio buttons and then change the background color of the selected item or something.
这一切都可以在没有 JavaScript 的情况下工作,但是您可能希望添加一些来隐藏单选按钮,然后更改所选项目的背景颜色或其他内容。
Bear in mind, this is far from a perfect solution, but if you absolutely need a nested select with reasonable cross-browser compatibility, this is probably as close as you're going to get.
请记住,这远不是一个完美的解决方案,但是如果您绝对需要具有合理跨浏览器兼容性的嵌套选择,那么这可能与您将要获得的一样接近。
回答by Matija Nalis
I needed clean and lightweight solution (so no jQuery and alike), which will look exactly like plain HTML, would also continue working when only plain HTML is preset (so javascript will only enhance it), and which will allow searching by starting letters (including national UTF-8 letters) if possible where it does not add extra weight. It also must work fast on very slow browsers (think rPi - so preferably no javascript executing after page load).
我需要干净和轻量级的解决方案(所以没有 jQuery 之类的),它看起来和纯 HTML 完全一样,当只预设纯 HTML 时也可以继续工作(所以 javascript 只会增强它),并且允许通过起始字母搜索(包括国家 UTF-8 字母)如果可能的话,它不会增加额外的重量。它还必须在非常慢的浏览器上快速运行(想想 rPi - 所以最好不要在页面加载后执行 javascript)。
In firefox it uses CSS identing and thus allow searching by letters, and in other browsers it will use
prepending (but there it does not support quick search by letters). Anyway, I'm quite happy with results.
在 firefox 中,它使用 CSS 识别,因此允许按字母搜索,而在其他浏览器中,它将使用
前置(但它不支持按字母快速搜索)。无论如何,我对结果很满意。
You can try it in action here
你可以在这里尝试
It goes like this:
它是这样的:
CSS:
CSS:
.i0 { }
.i1 { margin-left: 1em; }
.i2 { margin-left: 2em; }
.i3 { margin-left: 3em; }
.i4 { margin-left: 4em; }
.i5 { margin-left: 5em; }
HTML (class "i1", "i2" etc denote identation level):
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:
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();
}
}