问题描述
我正在寻找一种同时折叠/展开多个表格的方法,我在此站点上找到了以下方法:
<button type="button" data-parent="#wrap" data-toggle="collapse" data-target=".demo">
simple collapsible
</button>
<div id="wrap">
<div class="demo collapse">
test1
</div>
<div class="demo collapse">
test1
</div>
</div>
基本上,这工作正常,但我注意到它也在折叠/展开具有其他父 ID 的其他表。我需要的是两个按钮,每个按钮可以展开/折叠多个表格。 由于这些表是动态生成的,它们都获得了一个具有相同开头的类名。
<button type="button" data-parent="#wrap1" data-toggle="collapse" data-target=".demo">
simple collapsible 1
</button>
<div id="wrap">
<div class="demo collapse 1a">
test1
</div>
<div class="demo collapse 1b">
test1
</div>
</div>
<button type="button" data-parent="#wrap2" data-toggle="collapse" data-target=".demo">
simple collapsible 2
</button>
<div id="wrap2">
<div class="demo collapse 2a">
test1
</div>
<div class="demo collapse 2b">
test1
</div>
</div>
一些背景信息,我收到了一个 webtool,它是用 Python、Django 和 Iommi 的组合创建的。我们的实习生创建了这个非常好的工具,一些用户提出了一些改进要求。
创建不同车道(行)的模板 HTML,每个车道都包含它自己的一组表格。目前,每个桌子和每个泳道都包含一个展开/折叠按钮,属于桌子的按钮工作正常,但属于泳道的按钮正在操纵所有桌子,而不仅仅是属于该泳道的桌子。
模板 HTML:
{% load django_bootstrap_icons %}
{% load mathfilters %}
{% load markdownify %}
<div class="align-self-center" id="lanetypegrouper-{{lanetype.grouper}}">
{% for lane in lanetype.list %}
{% regroup lane.blocks.all|dictsort:"position" by position as tblock_positiongroups %}
<div class="card
{% if lane.type == 'DIE' %}border-primary {% endif %}
{% if lane.type == 'FIN' %}border-info {% endif %}
{% if lane.type == 'PRE' %}border-warning {% endif %}
{% if lanetype.grouper == False%} ml-auto {% endif%}
m-2
tlanetype
lanetype-{{lane.type}}
"
id="lane-{{lane.uuid}}"
{% with lanewidth=tblock_positiongroups|length|mul:12|add:1 %} style="width:{{lanewidth}}rem; min-width:11rem" {% endwith%}>
<script>
var btnUp = '{% bs_icon "chevron-up" %}';
var btnDown = '{% bs_icon "chevron-down" %}';
function change_btn(objButton)
{
var btnval = objButton.innerHTML;
$(".collapse").on('hidden.bs.collapse',function(){
if (btnval===btnDown) objButton.innerHTML = btnUp;
else objButton.innerHTML = btnDown;
});
$(".collapse").on('shown.bs.collapse',function(){
if (btnval===btnDown) objButton.innerHTML = btnUp;
else objButton.innerHTML = btnDown;
});
}
function change_row_btn(objButton)
{
var btnval = objButton.innerHTML;
$(".collapse").on('hidden.bs.collapse',function(){
if (btnval===btnDown) objButton.innerHTML = btnUp;
else objButton.innerHTML = btnDown;
});
$(".collapse").on('shown.bs.collapse',function(){
if (btnval===btnDown) objButton.innerHTML = btnUp;
else objButton.innerHTML = btnDown;
});
}
</script>
<div class="card-header p-2">
{{lane.get_type_display}}: {{lane.name}}
<a class="btn btn-sm btn-outline-secondary p-1 small" role="button" href="{% url 'laneedit' lane.pk %}">{% bs_icon 'pencil-fill' %} Edit Row</a>
<a class="btn btn-sm btn-outline-secondary p-1 small"
type="button"
data-toggle="collapse"
data-parent="#row-{{lane.uuid}}"
data-target=".collapse"
aria-expanded="true"
aria-controls="collapseExample"
onclick="change_row_btn(this)"
>{% bs_icon "chevron-down" %}</a>
</div>
<div class="card-body">
<div id="row-{{lane.uuid}}" class="row {% if lanetype.grouper == False %}float-right{%endif%}">
{% for blockgroup in tblock_positiongroups%}
<div class="col tlane-position p-1 m-0" id="laneposition-{{blockgroup.grouper}}">
{% for tblock in blockgroup.list%}
<div class="card
{% if lane.type == 'DIE' %}border-primary text-white{% endif %}
{% if lane.type == 'FIN' %}border-info text-white {% endif %}
{% if lane.type == 'PRE' %}border-warning {% endif %}
tblock-card"
id="block-{{tblock.uuid}}">
<div class="card-header p-1
{% if tblock.notForRelease %}
text-white bg-secondary
{% else %}
{% if lane.type == 'DIE' %}bg-primary {% endif %}
{% if lane.type == 'FIN' %}bg-info {% endif %}
{% if lane.type == 'PRE' %}bg-warning {% endif %}
{% endif %}
">
<div class="row">
<div class="col" style="padding-right:0">
<b>{{tblock.type}}</b> {% if tblock.typeCounter > 0 %}{{tblock.typeCounter}}{%endif%}
</div>
<div class="col-auto small">
<button class="btn btn-sm p-1
{% if lane.type == 'PRE' %}btn-outline-dark {%else %} btn-outline-light {% endif %}
small tblock-collapsebtn"
type="button"
data-toggle="collapse"
data-target="#collapsable-{{tblock.uuid}}"
aria-expanded="false"
aria-controls="collapseExample"
onclick="change_btn(this)"
>{% bs_icon "chevron-down" %}</button>
<a class="btn btn-sm p-1
{% if lane.type == 'PRE' %}btn-outline-dark {%else %} btn-outline-light {% endif %}
p-1 small"
role="button"
href="{% url 'blockedit' tblock.pk %}">
{% bs_icon 'pencil-fill' %}
</a>
</div>
</div>
{% if tblock.notForRelease %}<span class="small">(SafeLaunch)</span> {% endif %}
</div>
<div class="card-body p-0">{% include 'blocktable.html'%}</div>
<div class="card-footer p-1 m-0"><span class="text-muted small tblock_remarks">{{tblock.remarks|markdownify}}</span></div>
</div>
{% endfor %} {% comment %} tblocks {% endcomment %}
</div>
{% endfor%} {% comment %} tblock grouplist {% endcomment %}
</div>
</div>
{% if lane.desc %}<div class="card-footer">{{lane.desc}}</div>{%endif%}
</div>
{% endfor %}
</div>
解决方法
我不知道这是不是最好的解决方案,但我用下面的代码解决了。
<script>
var btnUp = '{% bs_icon "chevron-up" %}';
var btnDown = '{% bs_icon "chevron-down" %}';
function change_btn(objButton)
{
var btnval = objButton.innerHTML;
$(".collapse").on('hidden.bs.collapse',function(){ objButton.innerHTML = btnDown });
$(".collapse").on('shown.bs.collapse',function(){ objButton.innerHTML = btnUp; });
}
function change_row_btn(objButton)
{
var lane_id = objButton.offsetParent.id;
var btnval = objButton.innerHTML;
var lane_element = "";
var ids = document.querySelectorAll('*[id]:not([id=""])')
Array.prototype.forEach.call( ids,function( element,i ) {
if (element.id === lane_id) { lane_element = element; }
});
var new_state = "hide"
var ids = lane_element.querySelectorAll('*[id^="collapsable-"]:not([id=""])');
Array.prototype.forEach.call( ids,i ) {
if (btnval===btnDown) {
new_state = "show"
objButton.innerHTML = btnUp;
$(element).data('toggle','collapse').collapse('show');
} else {
new_state = "hide"
objButton.innerHTML = btnDown;
$(element).data('toggle','collapse').collapse('hide');
}
});
var ids = lane_element.querySelectorAll('*[id^="btn-"]:not([id=""])');
Array.prototype.forEach.call( ids,function( step_btn_element,i ) {
if (new_state==="show") { step_btn_element.innerHTML = btnUp; }
else { step_btn_element.innerHTML = btnDown; }
});
}
</script>