How do I detect when all items have been manually changed to either aria-expanded="false"
or aria-expanded="true"
in order to trigger the change in the click function. Currently the click trigger isn't smart enough to know when all items have the same state to allow the next click to either expand/collapse all.
If you collapse all of the items manually and then try to toggle the button, you will have to click it twice in order to reset the state. I am hoping to have this done automatically by detecting when all of the items have been manually changed to the same state.
$(function() {
$(".collapsable-basic").collapsable({
accordion: false,
fx: "toggle",
collapsableAll: true
});
$(".collapsable-basic").collapsable("expandAll");
jQuery.fn.clickToggle = function(a, b) {
return this.on("click", function(evt) {
[b, a][(this.$_io ^= 1)].call(this, evt);
});
};
$(".btn-primary").clickToggle(
function(evt) {
evt.preventDefault();
$(this).text("expand");
$(".collapsable-basic").collapsable("collapseAll");
},
function(evt) {
$(this).text("collapse");
$(".collapsable-basic").collapsable("expandAll");
}
);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.statically.io/gist/moofawsaw/696afac8210ff49f0224e2e6fecb4f0f/raw/cd8c6aec13b9453d9bf2952c242bdfd61980f134/pairpal-collapsable.js"></script>
<button class="btn btn-primary expand-all">collapse</button>
<div class="collapsable collapsable-basic">
<h4 class="ca-control">
Box 1
</h4>
<div class="ca-box">
<p>
Aliquam
</p>
</div>
</div>
<div class="collapsable collapsable-basic">
<h4 class="ca-control">
Box 2
</h4>
<div class="ca-box">
<p>
Fusce nibh magna.
</p>
</div>
</div>
<div class="collapsable collapsable-basic">
<h4 class="ca-control">
Box 3
</h4>
<div class="ca-box">
<p>
Quisque lobortis\.
</p>
</div>
</div>
The solution that would require the least amount of changes to what you already have would probably be to add an additional check when an element is expanded or collapsed that will flip the state of your button when all elements are closed or when all elements are opened and the expand/collapse button has the incorrect state.
You can add a conditional after the event handler for expanding/collapsing a single element like this:
//If everything is visible
if($(".ca-box:visible").length == $(".ca-box").length && $(".btn-primary").text() == "expand"){
$(".btn-primary").click()
}
//Else if everything is invisible
else if($(".ca-box:hidden").length == $(".ca-box").length && $(".btn-primary").text() == "collapse"){
$(".btn-primary").click()
}
After an element is expanded/collapsed, if one of these checks is true, the button will get clicked automatically to revert its state to what it should be.
Edit adding snippet:
I'm not sure how you would do it with the libraries you are using, but this is how I would do it using only jquery:
$('.ca-control').click(function(){
$(this).next().toggle()
//If everything is visible
if($(".ca-box:visible").length == $(".ca-box").length){
$('#toggleAll').text("collapse");
}
//Else if everything is invisible
else if($(".ca-box:hidden").length == $(".ca-box").length){
$('#toggleAll').text("expand");
}
});
$('#toggleAll').click(function(){
if($(this).text()=='collapse'){
$('.ca-box').hide();
$(this).text('expand');
}else{
$('.ca-box').show();
$(this).text('collapse');
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.statically.io/gist/moofawsaw/696afac8210ff49f0224e2e6fecb4f0f/raw/cd8c6aec13b9453d9bf2952c242bdfd61980f134/pairpal-collapsable.js"></script>
<button id="toggleAll" class="btn btn-primary expand-all">collapse</button>
<div class="collapsable collapsable-basic">
<h4 class="ca-control">
Box 1
</h4>
<div class="ca-box">
<p>
Aliquam
</p>
</div>
</div>
<div class="collapsable collapsable-basic">
<h4 class="ca-control">
Box 2
</h4>
<div class="ca-box">
<p>
Fusce nibh magna.
</p>
</div>
</div>
<div class="collapsable collapsable-basic">
<h4 class="ca-control">
Box 3
</h4>
<div class="ca-box">
<p>
Quisque lobortis\.
</p>
</div>
</div>