I would remove the id's from the buttons.
Changes:
- Remove the ID's from the open buttons
- Created two new open buttons to illustrate
- Close any open when a button is clicked Key change to the code for the questions ask
- Added a jQuery selector for the target to each button
data-target-canvas="#offcanvas2"
for example. This can be any valid jQuery selector
- Updated code to work by class I added to the buttons
offcanvas-open
instead of an ID - so as illustrated multiple buttons for one thing all work.
- This all can probably be even simpler with some minor updates to the elements but did not wish too stray too far from the original markup.
EDIT: Added a target to the X button (close) to point to the "prior"
// now just use the data attribute no matter what its target is
$("[data-target-canvas]").on("click", function() {
$('.offcanvas.offcanvas-start').offcanvas("hide");
const targ = $(this).data("target-canvas");
$(targ).first().offcanvas("show");
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<button class="btn btn-primary" type="button" data-target-canvas="#offcanvas1">Open Offcanvas 1</button>
<button class="btn btn-primary" type="button" data-target-canvas="#offcanvas2">Open Offcanvas 2</button>
<button class="btn btn-primary" type="button" data-target-canvas="#offcanvas3">Open Offcanvas 3</button>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas1">
<div class="offcanvas-header">
<h5 class="offcanvas-title">Offcanvas 1</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close" data-target-canvas="#offcanvas3"></button>
</div>
<div class="offcanvas-body">
<button class="btn btn-primary" type="button" data-target-canvas="#offcanvas3">Open Offcanvas 2</button>
</div>
</div>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas3">
<div class="offcanvas-header">
<h5 class="offcanvas-title">Offcanvas 3</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-target-canvas="#offcanvas2"></button>
</div>
<div class="offcanvas-body">
</div>
</div>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas2">
<div class="offcanvas-header">
<h5 class="offcanvas-title">Offcanvas 2</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-target-canvas="#offcanvas1"></button>
</div>
<div class="offcanvas-body">
<button class="btn btn-primary" type="button" data-target-canvas="#offcanvas1">Open Offcanvas 3</button>
</div>
</div>
Second example; forgo ANY class selectors so all we need to do is add the data attribute to any button etc. and it simple "works".
/* left in but commented out for clarity. Then added combined function do do both */
/*
$(".offcanvas-open").on("click", function() {
// hide any open
$('.offcanvas.offcanvas-start').offcanvas("hide");
const targ = $(this).data("target-canvas");
$(targ).first().offcanvas("show");
});
$(".close-me").on("click", function() {
$('.offcanvas.offcanvas-start').offcanvas("hide");
const targ = $(this).data("target-canvas");
$(targ).first().offcanvas("show");
});
*/
// now replace both those with ONE function:
$(".offcanvas-open").add(".close-me").on("click", function() {
$('.offcanvas.offcanvas-start').offcanvas("hide");
const targ = $(this).data("target-canvas");
$(targ).first().offcanvas("show");
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<button class="offcanvas-open btn btn-primary" type="button" data-target-canvas="#offcanvas1">Open Offcanvas 1</button>
<button class="offcanvas-open btn btn-primary" type="button" data-target-canvas="#offcanvas2">Open Offcanvas 2</button>
<button class="offcanvas-open btn btn-primary" type="button" data-target-canvas="#offcanvas3">Open Offcanvas 3</button>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas1">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasWithBothOptionsLabel">Offcanvas 1</h5>
<button type="button" class="close-me btn-close" data-bs-dismiss="offcanvas" aria-label="Close" data-target-canvas="#offcanvas3"></button>
</div>
<div class="offcanvas-body">
<button class="offcanvas-open btn btn-primary" type="button" data-target-canvas="#offcanvas3">Open Offcanvas 2</button>
</div>
</div>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas3">
<div class="offcanvas-header">
<h5 class="offcanvas-title">Offcanvas 3</h5>
<button type="button" class="close-me btn-close" data-bs-dismiss="offcanvas" data-target-canvas="#offcanvas2"></button>
</div>
<div class="offcanvas-body">
</div>
</div>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas2">
<div class="offcanvas-header">
<h5 class="offcanvas-title">Offcanvas 2</h5>
<button type="button" class="close-me btn-close" data-bs-dismiss="offcanvas" data-target-canvas="#offcanvas1"></button>
</div>
<div class="offcanvas-body">
<button class="offcanvas-open btn btn-primary" type="button" data-target-canvas="#offcanvas1">Open Offcanvas 3</button>
</div>
</div>
THIRD example; target the container class selectors so all we need to do is add the data attribute to any container; then hook it to the button classes and it simply "works".
/* Here we use the button class to determine the "next" target
* If the button is "btn-close" then we go to the target of our "pointed to" element.
* If the button is NOT a "btn-close" then we simply use OUR target-canvas element.
* Since we need it more than once, we create a string canvasTarget to reuse.
* "event.delegateTarget" is what the event is hooked to (things with a data-target-canvas)
* "event.target" is whatever is clicked (the buttons) from our list; whatever is ON a "type" of button"; we had these so just used them: ".btn-close, .btn.btn-primary"
*/
$("[data-target-canvas]")
.on("click", ".btn-close, .btn.btn-primary", function(event) {
$('.offcanvas.offcanvas-start').offcanvas("hide");
const canvasTarget = 'target-canvas';
const base = $(event.delegateTarget).data(canvasTarget);
const isClose = this.classList.contains('btn-close');
//go get the value of our targets target
const altTarg = $(base).data(canvasTarget);
// when true we use the alt else we used the base from our delegate
const nextTarg = isClose ? altTarg : base;
$(nextTarg).first().offcanvas("show");
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<span class="just-a-button" data-target-canvas="#offcanvas1">
<button class="btn btn-primary" type="button" >Open Offcanvas 1</button></span>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas1" data-target-canvas="#offcanvas2">
<div class="offcanvas-header">
<h5 class="offcanvas-title">Offcanvas 1</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<button class="btn btn-primary" type="button">Open Offcanvas 2</button>
</div>
</div>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas3" data-target-canvas="#offcanvas1">
<div class="offcanvas-header">
<h5 class="offcanvas-title">Offcanvas 3</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas"></button>
</div>
<div class="offcanvas-body">
</div>
</div>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas2" data-target-canvas="#offcanvas3">
<div class="offcanvas-header">
<h5 class="offcanvas-title">Offcanvas 2</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas"></button>
</div>
<div class="offcanvas-body">
<button class="btn btn-primary" type="button">Open Offcanvas 3</button>
</div>
</div>