Navigation als Bootstratp 5 Akkordeon in Cassiopeia
Wer mit Bootstrap vertraut ist und die Navigation als Akkordeon anpassen möchte, kann dies unkompliziert erledigen. Cassiopia ist ein Bootstrap 5 Template. So kann es Bootstrap Komponenten verwenden.
Ich habe ein Override erstellt, welches die wesentlichen Bootstrap Klassen und Attribute ergänzt, um die Navigation in einer Seitenleiste vertikal als Akkordeon anzuzeigen.
Die Bootstrap Dokumentation findest du unter der Adresse getbootstrap.com/docs[^https://getbootstrap.com/docs/].
Override anlegen
Anlegen müssen wir lediglich eine Datei. Die Datei /templates/cassiopeia/html/mod_menu/akkordeon.php
, wenn man Cassiopeia verwendet. Die Datei /templates/cassiopeia_child_name/html/mod_menu/akkordeon.php
, wenn man ein Child von Cassiopeia angelegt hat.
/templates/cassiopeia_yourchild/html/mod_menu/akkordeon.php
<?php
defined('_JEXEC') or die;
use Joomla\CMS\Helper\ModuleHelper;
$wa = $app->getDocument()->getWebAssetManager();
$wa->useScript('bootstrap.collapse');
$id = '';
$unique = uniqid();
if ($tagId = $params->get('tag_id', '')) {
$id = ' id="' . $tagId . '"';
} else {
$id = ' id="accordion' . $unique . '"';
}
?>
<div class="accordion" id="<?php echo $id ?>">
<?php foreach ($list as $i => &$item) : ?>
<?php
$itemParams = $item->getParams();
$class = 'nav-item item-' . $item->id;
if ($item->id == $default_id) {
$class .= ' default';
}
if ($item->id == $active_id || ($item->type === 'alias' && $itemParams->get('aliasoptions') == $active_id)) {
$class .= ' current';
}
if (in_array($item->id, $path)) {
$class .= ' active';
} elseif ($item->type === 'alias') {
$aliasToId = $itemParams->get('aliasoptions');
if (count($path) > 0 && $aliasToId == $path[count($path) - 1]) {
$class .= ' active';
} elseif (in_array($aliasToId, $path)) {
$class .= ' alias-parent-active';
}
}
if ($item->type === 'separator') {
$class .= ' divider';
}
if ($item->deeper) {
$class .= ' deeper';
}
if ($item->parent) {
$class .= ' parent';
}
if ($item->shallower) {
$class .= ' shallower';
}
?>
<?php if ($item->deeper) : ?>
<div class="accordion-item">
<h2 class="accordion-header" id="panelsStayOpen-heading<?php echo $item->id . $i ?>">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#panelsStayOpen-collapse<?php echo $item->id . $i ?>" aria-expanded="true"
aria-controls="panelsStayOpen-collapse<?php echo $item->id . $i ?>">
<?php echo $item->title ?>
</button>
</h2>
<div id="panelsStayOpen-collapse<?php echo $item->id . $i ?>" class="accordion-collapse collapse noshow"
aria-labelledby="panelsStayOpen-heading<?php echo $item->id . $i ?>">
<div class="accordion-body">
<?php endif; ?>
<?php if ($item->shallower): ?>
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button accordion-button-fake" type="button">
<?php
switch ($item->type) :
case 'separator':
case 'component':
case 'url':
require ModuleHelper::getLayoutPath('mod_menu', 'default_' . $item->type);
break;
case 'heading':
break;
default:
require ModuleHelper::getLayoutPath('mod_menu', 'default_url');
break;
endswitch;
?>
</button>
</h2>
</div>
</div>
</div>
</div>
<?php endif; ?>
<?php if (!$item->shallower && !$item->deeper): ?>
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button accordion-button-fake" type="button">
<?php
switch ($item->type) :
case 'separator':
case 'component':
case 'url':
require ModuleHelper::getLayoutPath('mod_menu', 'default_' . $item->type);
break;
case 'heading':
break;
default:
require ModuleHelper::getLayoutPath('mod_menu', 'default_url');
break;
endswitch;
?>
</button>
</h2>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
var collapses = document.querySelectorAll(".collapse");
function handleCollapseShow() {
localStorage.setItem("coll_" + this.id, true);
}
function handleCollapseHide() {
localStorage.removeItem("coll_" + this.id);
}
function checkCollapseState() {
var id = this.id;
var storedState = localStorage.getItem("coll_" + id);
if (storedState === "true") {
this.classList.add("show");
} else {
this.classList.remove("show");
}
}
Array.from(collapses).forEach(function(collapse) {
collapse.addEventListener("shown.bs.collapse", handleCollapseShow);
collapse.addEventListener("hidden.bs.collapse", handleCollapseHide);
checkCollapseState.call(collapse);
});
});
</script>
Das Skript am Ende der PHP-Datei ist optional. Du brauchst es nur, wenn du den Zustand des Akkordeons speichern willst. Ohne den JavaScript-Code wird das Akkordeon nach dem Klicken auf einen Menüpunkt immer vollständig geöffnet angezeigt. Das Skript sorgt dafür, dass sich der Browser merkt, welche Bereiche des Akkordeons geöffnet und welche geschlossen sind.
Override auswählen
Last but not least ist erforderlich im Modul des Menüs das Layout für das Akkordeon auszuwählen und die gewünschte Position festzulegen.