我创建了一个客户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行为?
答案 0 :(得分:62)
这里的HTML规范真的坏了。它应该允许嵌套的optgroup并建议用户代理将它们渲染为嵌套菜单。相反,only one optgroup level is allowed。 但是,他们必须在这个问题上说以下内容:
请注意。建议实现者,HTML的未来版本可以扩展分组机制以允许嵌套组(即,OPTGROUP元素可以嵌套)。这将允许作者代表更丰富的选择层次。
用户代理可以开始使用子菜单来呈现optgoups,而不是像现在那样在optgroup中的第一个选项元素之前显示标题。
答案 1 :(得分:46)
这很好,但是如果你添加不在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>
答案 2 :(得分:40)
好的,如果有人读过这个:最好的选择是在每个额外的缩进级别添加四个
,看起来好像!
所以:
<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>
答案 3 :(得分:7)
<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>
答案 4 :(得分:5)
我认为如果你有一些结构复杂的东西,你可能会考虑一个单独的下拉框之外的东西。
答案 5 :(得分:5)
我非常喜欢这篇文章中的Broken Arrow's 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;
}
答案 6 :(得分:3)
我知道这是很久以前的事了,不过我还有一点额外补充:
这在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 :(得分:3)
我需要干净轻巧的解决方案(所以没有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”等表示标识级别):
<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 :(得分:2)
我写了一个漂亮的嵌套选择。也许会对您有帮助。
https://jsfiddle.net/nomorepls/tg13w5r7/1/
function on_change_select(e) {
alert(e.value, e.title, e.option, e.select);
}
$(document).ready(() => {
// NESTED SELECT
$(document).on('click', '.nested-cell', function() {
$(this).next('div').toggle('medium');
});
$(document).on('change', 'input[name="nested-select-hidden-radio"]', function() {
const parent = $(this).closest(".nested-select");
const value = $(this).attr('value');
const title = $(this).attr('title');
const executer = parent.attr('executer');
if (executer) {
const event = new Object();
event.value = value;
event.title = title;
event.option = $(this);
event.select = parent;
window[executer].apply(null, [event]);
}
parent.attr('value', value);
parent.parent().slideToggle();
const button = parent.parent().prev();
button.toggleClass('active');
button.addClass('selected');
button.children('.nested-select-title').html(title);
});
$(document).on('click', '.nested-select-button', function() {
const button = $(this);
let select = button.parent().children('.nested-select-wrapper');
if (!button.hasClass('active')) {
select = select.detach();
if (button.height() + button.offset().top + $(window).height() * 0.4 > $(window).height()) {
select.insertBefore(button);
select.css('margin-top', '-44vh');
select.css('top', '0');
} else {
select.insertAfter(button);
select.css('margin-top', '');
select.css('top', '40px');
}
}
select.slideToggle();
button.toggleClass('active');
});
});
.container {
width: 200px;
position: relative;
top: 0;
left: 0;
right: 0;
height: auto;
}
.nested-select-box {
font-family: Arial, Helvetica, sans-serif;
display: block;
position: relative;
width: 100%;
height: fit-content;
cursor: pointer;
color: #2196f3;
height: 40px;
font-size: small;
/* z-index: 2000; */
}
.nested-select-box .nested-select-button {
border: 1px solid #2196f3;
position: absolute;
width: calc(100% - 20px);
padding: 0 10px;
min-height: 40px;
word-wrap: break-word;
margin: 0 auto;
overflow: hidden;
}
.nested-select-box.danger .nested-select-button {
border: 1px solid rgba(250, 33, 33, 0.678);
}
.nested-select-box .nested-select-button .nested-select-title {
padding-right: 25px;
padding-left: 25px;
width: calc(100% - 50px);
margin: auto;
height: fit-content;
text-align: center;
vertical-align: middle;
position: absolute;
top: 0;
bottom: 0;
left: 0;
}
.nested-select-box .nested-select-button.selected .nested-select-title {
bottom: unset;
top: 5px;
}
.nested-select-box .nested-select-button .nested-select-title-icon {
position: absolute;
height: 20px;
width: 20px;
top: 10px;
bottom: 10px;
right: 7px;
transition: all 0.5s ease 0s;
}
.nested-select-box .nested-select-button.active .nested-select-title-icon {
-moz-transform: scale(-1, -1);
-o-transform: scale(-1, -1);
-webkit-transform: scale(-1, -1);
transform: scale(-1, -1);
}
.nested-select-box .nested-select-button .nested-select-title-icon::before,
.nested-select-box .nested-select-button .nested-select-title-icon::after {
content: "";
background-color: #2196f3;
position: absolute;
width: 70%;
height: 2px;
transition: all 0.5s ease 0s;
top: 9px;
}
.nested-select-box .nested-select-button .nested-select-title-icon::before {
transform: rotate(45deg);
left: -1.6px;
}
.nested-select-box .nested-select-button .nested-select-title-icon::after {
transform: rotate(-45deg);
left: 7px;
}
.nested-select-box .nested-select-wrapper {
width: 100%;
top: 40px;
position: relative;
border: 1px solid #2196f3;
background: #ffffff;
z-index: 2005;
opacity: 1;
}
.nested-select {
font-family: Arial, Helvetica, sans-serif;
display: inline-block;
overflow-y: scroll;
max-height: 40vh;
width: calc(100% - 10px);
padding: 5px;
-ms-overflow-style: none;
scrollbar-width: none;
}
.nested-select::-webkit-scrollbar {
display: none;
}
.nested-select a,
.nested-select span {
padding: 0 5px;
border-radius: 3px;
cursor: pointer;
text-align: start;
}
.nested-select a:hover {
background-color: #62b2f3;
color: #ffffff;
}
.nested-select span:hover {
background-color: #c4c4c4;
color: #ffffff;
}
.nested-select input[type="radio"] {
display: none;
}
.nested-select input[type="radio"]+span {
display: block;
}
.nested-select input[type="radio"]:checked+span {
background-color: #2196f3;
color: #ffffff;
}
.nested-select div {
margin-left: 15px;
}
.nested-select label>span:before,
.nested-select a:before {
content: "\2022";
margin-right: 5px;
}
.nested-select a {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="nested-select-box w-100">
<div class="nested-select-button">
<p class="nested-select-title">
Account
</p>
<span class="nested-select-title-icon"></span>
</div>
<div class="nested-select-wrapper" style="display: none;">
<div class="nested-select" executer="on_change_select">
<label>
<input title="Accounting and legal services" value="1565142000000891539" type="radio" name="nested-select-hidden-radio">
<span>Accounting and legal services</span>
</label>
<label>
<input title="Advertising agencies" value="1565142000000891341" type="radio" name="nested-select-hidden-radio">
<span>Advertising agencies</span>
</label>
<a class="nested-cell">Advertising And Marketing</a>
<div>
<label>
<input title="Advertising agencies" value="1565142000000891341" type="radio" name="nested-select-hidden-radio">
<span>Advertising agencies</span>
</label>
<a class="nested-cell">Adwords - traffic</a>
<div>
<label>
<input title="Adwords - traffic: Charters and general search" value="1565142000003929177" type="radio" name="nested-select-hidden-radio">
<span>Adwords - traffic: Charters and general search</span>
</label>
<label>
<input title="Adwords - traffic: Distance course" value="1565142000007821291" type="radio" name="nested-select-hidden-radio">
<span>Adwords - traffic: Distance course</span>
</label>
<label>
<input title="Adwords - traffic: Events" value="1565142000003929189" type="radio" name="nested-select-hidden-radio">
<span>Adwords - traffic: Events</span>
</label>
<label>
<input title="Adwords - traffic: Practices" value="1565142000003929165" type="radio" name="nested-select-hidden-radio">
<span>Adwords - traffic: Practices</span>
</label>
<label>
<input title="Adwords - traffic: Sailing tours" value="1565142000003929183" type="radio" name="nested-select-hidden-radio">
<span>Adwords - traffic: Sailing tours</span>
</label>
<label>
<input title="Adwords - traffic: Theoretical courses" value="1565142000003929171" type="radio" name="nested-select-hidden-radio">
<span>Adwords - traffic: Theoretical courses</span>
</label>
</div>
<label>
<input title="Branded products" value="1565142000000891533" type="radio" name="nested-select-hidden-radio">
<span>Branded products</span>
</label>
<label>
<input title="Business cards" value="1565142000005438323" type="radio" name="nested-select-hidden-radio">
<span>Business cards</span>
</label>
<a class="nested-cell">Facebook, Instagram - traffic</a>
<div>
<label>
<input title="Facebook, Instagram - traffic: Charters and general search" value="1565142000003929145" type="radio" name="nested-select-hidden-radio">
<span>Facebook, Instagram - traffic: Charters and general search</span>
</label>
<label>
<input title="Facebook, Instagram - traffic: Distance course" value="1565142000007821285" type="radio" name="nested-select-hidden-radio">
<span>Facebook, Instagram - traffic: Distance course</span>
</label>
<label>
<input title="Facebook, Instagram - traffic: Events" value="1565142000003929157" type="radio" name="nested-select-hidden-radio">
<span>Facebook, Instagram - traffic: Events</span>
</label>
<label>
<input title="Facebook, Instagram - traffic: Practices" value="1565142000003929133" type="radio" name="nested-select-hidden-radio">
<span>Facebook, Instagram - traffic: Practices</span>
</label>
<label>
<input title="Facebook, Instagram - traffic: Sailing tours" value="1565142000003929151" type="radio" name="nested-select-hidden-radio">
<span>Facebook, Instagram - traffic: Sailing tours</span>
</label>
<label>
<input title="Facebook, Instagram - traffic: Theoretical courses" value="1565142000003929139" type="radio" name="nested-select-hidden-radio">
<span>Facebook, Instagram - traffic: Theoretical courses</span>
</label>
</div>
<label>
<input title="Offline Advertising (posters, banners, partnerships)" value="1565142000000891377" type="radio" name="nested-select-hidden-radio">
<span>Offline Advertising (posters, banners, partnerships)</span>
</label>
<label>
<input title="Photos, video etc." value="1565142000000891371" type="radio" name="nested-select-hidden-radio">
<span>Photos, video etc.</span>
</label>
<label>
<input title="Prize fund" value="1565142000001404931" type="radio" name="nested-select-hidden-radio">
<span>Prize fund</span>
</label>
<label>
<input title="SEO" value="1565142000000891365" type="radio" name="nested-select-hidden-radio">
<span>SEO</span>
</label>
<label>
<input title="SMM Content creation (texts, copywriting)" value="1565142000000891389" type="radio" name="nested-select-hidden-radio">
<span>SMM Content creation (texts, copywriting)</span>
</label>
<a class="nested-cell">YouTube</a>
<div>
<label>
<input title="YouTube: travel expenses" value="1565142000008100163" type="radio" name="nested-select-hidden-radio">
<span>YouTube: travel expenses</span>
</label>
<label>
<input title="Youtube: video editing" value="1565142000008100157" type="radio" name="nested-select-hidden-radio">
<span>Youtube: video editing</span>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
答案 9 :(得分:0)
似乎该标准的最初发明者想要一个基于组的选择列表,而不是一个分层列表。不幸的是,由于破坏向下兼容性的风险很高,未来的 HTML 标准可能不会改变这一点。
如果可以接受,将分层列表转换为段命名组列表可能是一种解决方法:
<select>
<optgroup label="Level One">
<option> A.1 </option>
</optgroup>
<optgroup label="Level One / Level Two">
<option> A.B.1 </option>
</optgroup>
<optgroup label="Level One">
<option> A.2 </option>
</optgroup>
</select>
如果可以接受订单更改,请考虑合并具有相同组名的项目以获得更好的外观:
<select>
<optgroup label="Level One">
<option> A.1 </option>
<option> A.2 </option>
</optgroup>
<optgroup label="Level One / Level Two">
<option> A.B.1 </option>
</optgroup>
</select>
如果两者都不可接受并且确实需要分层选择列表,则可能需要实现带有复选框的模态对话框(可能还有一些用于使用 Shift 或 Ctrl 键进行多选的 JavaScript 键盘陷阱)。
答案 10 :(得分:0)
我采用这种方法是因为我找不到我要搜索的内容。嵌套的手风琴选择。它的 CSS 非常简单,可以改进。您唯一需要的是一个带有要添加到选择中的键和值的对象。 Keys
是子组,键 values
(数组和单个元素)是可选项目。
一旦你有了你的数组,你唯一需要做的就是调用
initAccordeon(obj);
以您的数据对象作为参数,将出现嵌套的手风琴:
const obj = {
Cars: {
SwedishCars: [
"Volvo",
"Saab"
],
GermanCars: [
"Mercedes",
{
Audi: [
"Audi A3",
"Audi A4",
"Audi A5"
]
}
]
},
Food: {
Fruits: [
"Orange",
"Apple",
"Banana"
],
SaltyFoods: [
"Pretzels",
"Burger",
"Noodles"
],
Drinks: "Water"
}
};
initAccordeon(obj); // <--------------------------- Call initialization
function accordeonAddEvents() {
Array.from(document.getElementsByClassName("accordeon-header")).forEach(function(header) {
if (header.getAttribute("listener") !== "true") {
header.addEventListener("click", function() {
this.parentNode.getElementsByClassName("accordeon-body")[0].classList.toggle("hide");
});
header.setAttribute("listener", "true");
}
});
Array.from(document.getElementsByClassName("button-group")).forEach(function(but) {
if (but.getAttribute("listener") !== "true") {
but.addEventListener("click", function() {
if (this.getAttribute("depth") === "-1") {
let header = this;
while ((header = header.parentElement) && header.className !== "accordeon");
header.getElementsByClassName("accordeon-header")[0].innerHTML = this.innerHTML;
return;
}
const groups = Array.from(this.parentNode.getElementsByClassName("accordeon-group"));
groups.forEach(g => {
if (g.getAttribute("uuid") === this.getAttribute("uuid") &&
g.getAttribute("depth") === this.getAttribute("depth")) {
g.classList.toggle("hide");
}
});
});
but.setAttribute("listener", "true");
}
});
}
function initAccordeon(data) {
accordeons = Array.from(document.getElementsByClassName("accordeon-body"));
accordeons.forEach(acc => {
acc.innerHTML = "";
const route = (subObj, keyIndex = 0, parent = acc, depth = 0) => {
const keys = Object.keys(subObj);
if (typeof subObj === 'object' && !Array.isArray(subObj) && keys.length > 0) {
while (keyIndex < keys.length) {
var but = document.createElement("button");
but.className = "button-group";
but.setAttribute("uuid", keyIndex);
but.setAttribute("depth", depth);
but.innerHTML = keys[keyIndex];
var group = document.createElement("div");
group.className = "accordeon-group hide";
group.setAttribute("uuid", keyIndex);
group.setAttribute("depth", depth);
route(subObj[keys[keyIndex]], 0, group, depth + 1);
keyIndex++;
parent.append(but);
parent.append(group);
}
} else {
if (!Array.isArray(subObj)) subObj = [subObj];
subObj.forEach((e, i) => {
if (typeof e === 'object') {
route(e, 0, parent, depth);
} else {
var but = document.createElement("button");
but.className = "button-group";
but.setAttribute("uuid", i);
but.setAttribute("depth", "-1");
but.innerHTML = e;
parent.append(but);
}
});
}
};
route(data);
});
accordeonAddEvents();
}
.accordeon {
width: 460px;
height: auto;
min-height: 340px;
font-size: 20px;
cursor: pointer;
user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
display: block;
position: relative;
z-index: 10;
}
.accordeon-header {
display: inline-block;
width: 450px;
border: solid 0.1vw black;
border-radius: 0.2vw;
background-color: white;
padding-left: 10px;
color: black;
}
.accordeon-header:hover {
opacity: 0.7;
}
.accordeon-body {
display: block;
position: absolute;
}
.button-group {
display: block;
cursor: pointer;
width: 460px;
text-align: left;
font-size: 20px;
font-weight: bold;
}
.accordeon-group {
padding-left: 20px;
}
.accordeon-group .button-group {
width: 100%;
}
.button-group[depth="-1"] {
color: green;
}
.hide {
display: none;
}
<div class="accordeon">
<span class="accordeon-header">Select something</span>
<div class="accordeon-body hide">
</div>
</div>