Reputation: 8081
My html which uses Bootstrap 4 and jquery 3.2.1, is generated by another script dynamically, and consists of several elements, whose basic unit looks like this:
<div class="card" style="width: 95%;">
<div class="card-body">
<h5 class="card-title"><div class="alert alert-secondary" role="alert"><h4>Question 24 of 2947</h4></div></h5>
<h5 class="card-header"><p>A 72-year-old lady was treated non-operatively following a closed fracture of the radial shaft. Which of the following late complications would you least likely expect to see?Select one answer only</p></h5>
<p class="card-text"></p><ul><li>(A) Algodystrophy</li><li>(B) Infection</li><li>(C) Non-union</li><li>(D) Tendon rupture</li><li>(E) Volkmann’s ischaemic contracture</li></ul><p></p>
</div>
</div>
<button class="btn btn-primary columbrium" type="button" data-toggle="collapse" data-target="#yyGOkFXx" aria-expanded="true" aria-controls="collapseExample">
Answer
</button>
<button class="btn btn-primary" type="button" id="ExpandAllBtnyyGOkFXx">Expand All</button>
<script>
$( "button[id^='ExpandAllBtn']" ).bind('click', function() {
$('.collapse').collapse('toggle');
if ($( ".collapse" ).first().hasClass( "show" )) {
$( "button[id^='ExpandAllBtn']" ).html('Collapse All');
} else {
$( "button[id^='ExpandAllBtn']" ).html('Expand All');
}
});
</script>
<div class="collapse show" id="yyGOkFXx" style="">
<div class="card" style="width: 95%;">
<div class="card-body">
<p class="card-text">
</p><h2>Explanation
</h2>
<div id="ctl00">
<p><strong>My text</strong></p>
</div><p></p>
</div>
</div></div>
The enclosed javascript is supposed to expand the collapsable bootstrap elements, and also change the name of the button text once a click happens. Though the code works when run in the console, it does not change the name of the button when the button is clicked, though the elements expand and collapse as expected. What can I be missing?
$( "button[id^='ExpandAllBtn']" ).bind('click', function() {
$('.collapse').collapse('toggle');
if ($( ".collapse" ).first().hasClass( "show" )) {
$( "button[id^='ExpandAllBtn']" ).html('Collapse All');
} else {
$( "button[id^='ExpandAllBtn']" ).html('Expand All');
}
});
<html>
<head>
<title>Collection 2018</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</head>
<body>
<div class="card" style="width: 95%;">
<div class="card-body">
<h5 class="card-title"><div class="alert alert-secondary" role="alert"><h4>Question 24 of 2947</h4></div></h5>
<h5 class="card-header"><p>A 72-year-old lady was treated non-operatively following a closed fracture of the radial shaft. Which of the following late complications would you least likely expect to see?Select one answer only</p></h5>
<p class="card-text"></p><ul><li>(A) Algodystrophy</li><li>(B) Infection</li><li>(C) Non-union</li><li>(D) Tendon rupture</li><li>(E) Volkmann’s ischaemic contracture</li></ul><p></p>
</div>
</div>
<button class="btn btn-primary columbrium" type="button" data-toggle="collapse" data-target="#yyGOkFXx" aria-expanded="true" aria-controls="collapseExample">
Answer
</button>
<button class="btn btn-primary" type="button" id="ExpandAllBtnyyGOkFXx">Expand All</button>
<div class="collapse show" id="yyGOkFXx" style="">
<div class="card" style="width: 95%;">
<div class="card-body">
<p class="card-text">
</p><h2>Explanation
</h2>
<div id="ctl00">
<p><strong>My text</strong></p>
</div><p></p>
</div>
</div></div>
</body>
</html>
My fiddle: https://jsfiddle.net/7rupvont/
To be clear, my working example does expand and collapse elements fine. I'm unable to change the innerhtml of matching elements within displayed html, but able to do so in the console window. There are no delayed loading elements, as is evident from the code snippet/jsfiddle.
Upvotes: 1
Views: 66
Reputation: 171
Alright, due to the asynchronicity of Bootstraps collapse this did not work. In the interest of actually showing a differnet answer to dferencs i have changed mine into a workaround that does not require as many event listeners:
$("button[id^='ExpandAllBtn']").on("click", function() {
$(".collapse").collapse("toggle");
if (($("button[id^='ExpandAllBtn']" ).html() === "Collapse All") && !$(".collapse").first().hasClass("show")) {
$("button[id^='ExpandAllBtn']" ).html("Expand All");
} else {
$("button[id^='ExpandAllBtn']" ).html("Collapse All");
}
});
Upvotes: 0
Reputation: 8126
The reason is that all Bootstrap 4 methods are asynchronous, so when you call .collapse()
, it just starts the transition, but immediately returns to the rest of your script. This phenomenon is described under the Methods section of the Collapse component.
If you console.log
the value of $('.collapse').first().hasClass('show')
within your script, you will see that it is always equals to false
. The collapsible element does not receive the .show
class immediately when it is about to be shown, but loses it immediately when it is about to be hidden.
A solution to this problem is to use the Events that a Collapse component emits when toggled. Below you will find a snippet that does that.
// jQuery `.bind()` has been deprecated, use `.on()` instead
$("button[id^='ExpandAllBtn']").on('click', function() {
$('.collapse').collapse('toggle');
// $('.collapse').first().hasClass('show') is always false here
console.log($('.collapse').first().hasClass('show'));
});
$('.collapse').first().on('shown.bs.collapse', function () {
$("button[id^='ExpandAllBtn']").html('Collapse All');
});
$('.collapse').first().on('hidden.bs.collapse', function () {
$("button[id^='ExpandAllBtn']").html('Expand All');
});
<div class="card" style="width: 95%;">
<div class="card-body">
<h5 class="card-title"><div class="alert alert-secondary" role="alert"><h4>Question 24 of 2947</h4></div></h5>
<h5 class="card-header"><p>A 72-year-old lady was treated non-operatively following a closed fracture of the radial shaft. Which of the following late complications would you least likely expect to see?Select one answer only</p></h5>
<p class="card-text"></p><ul><li>(A) Algodystrophy</li><li>(B) Infection</li><li>(C) Non-union</li><li>(D) Tendon rupture</li><li>(E) Volkmann’s ischaemic contracture</li></ul><p></p>
</div>
</div>
<button class="btn btn-primary columbrium" type="button" data-toggle="collapse" data-target="#yyGOkFXx" aria-expanded="true" aria-controls="collapseExample">Answer</button>
<button class="btn btn-primary" type="button" id="ExpandAllBtnyyGOkFXx">Expand All</button>
<div class="collapse" id="yyGOkFXx" style="">
<div class="card" style="width: 95%;">
<div class="card-body">
<h2>Explanation</h2>
<div id="ctl00">
<p><strong>My text</strong></p>
</div>
</div>
</div>
</div>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
Note: As of jQuery 3.0, the .bind() method has been deprecated, and you should use .on()
instead.
Upvotes: 2