Skip to content

Instantly share code, notes, and snippets.

@wsydney76
Last active February 29, 2024 19:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save wsydney76/632bca3cda5382676fcee0e70c50d045 to your computer and use it in GitHub Desktop.
Save wsydney76/632bca3cda5382676fcee0e70c50d045 to your computer and use it in GitHub Desktop.
Make sections of Craft 5 element indexes collapsible
/* toggle sidebar visibility */
#sidebar li.heading > span {
font-size: 14px;
letter-spacing: 1px;
display: block;
}
#sidebar ul li.heading > span {
cursor: pointer;
}
#sidebar ul li.heading > span:hover::after {
content: ' [-]';
font-weight: normal;
font-size: 10px;
}
/* TODO: Check how to avoid vertical shift on hover without this hack: */
#sidebar ul li.heading > span::after {
content: ' ';
font-weight: normal;
font-size: 10px;
}
#sidebar ul li.heading.collapsed > span::after {
content: ' [+]';
font-weight: normal;
font-size: 10px;
}
#sidebar li.heading.collapsed ul {
display: none;
}
/*
DOM Structure:
#sidebar
nav
ul
li.heading <-- toggle class 'collapsed' here
span <-- The heading text, add click eventListener here
ul <-- the sources, toggle visiblity via css .collapsed -> ul
Known issues:
This script kicks in once the element index page is fully loaded, so there is some "flash of content" for collapsed sections.
Visibility does not get refreshed when changing sites via the sitemenu.
Depends on heading names, so will be reset if headings are changed.
Styling may cause issues when plugins/modules use the same dom structure. May be solved with more specific CSS rules.
*/
['entries','assets','categories','users'].forEach(elementType => {
if (isElementIndex(elementType)) {
initSidebarVisibility(elementType)
}
})
function isElementIndex(elementType) {
urlSegments = window.location.pathname.split("/");
return urlSegments.length >= 3 && urlSegments[2] === elementType
}
function initSidebarVisibility(elementType) {
// get headings
headingNodes = document.querySelectorAll('#sidebar li.heading > span')
// set visibility as stored in localStorage
setSidebarVisibility(elementType, headingNodes);
// Toggle sources visiblity on click
headingNodes.forEach(item => {
item.addEventListener('click', event => {
event.target.parentElement.classList.toggle('collapsed')
storeSidebarVisibility(elementType, headingNodes)
})
})
}
// store settings in local storage
function storeSidebarVisibility(elementType, headingNodes) {
var v = {};
headingNodes.forEach(function(element) {
v[element.innerText] = element.parentElement.classList.contains('collapsed') ? 'hidden' : 'visible'
});
localStorage[getStorageName(elementType)] = JSON.stringify(v);
}
function setSidebarVisibility(elementType, headingNodes) {
var v = localStorage[getStorageName(elementType)];
// No stored settings?
if (v === undefined) {
return;
}
v = JSON.parse(v);
headingNodes.forEach( (element, index) => {
if (element.innerText in v && v[element.innerText] === 'hidden') {
element.parentElement.classList.add('collapsed');
}
})
}
function getStorageName(elementType) {
urlParams = new URLSearchParams(window.location.search)
site = urlParams.get('site')
return 'sidebarVisiblity_' + site + '_' + elementType
}
<?php
namespace modules\main\web\assets\collapsesidebar;
use craft\web\AssetBundle;
/**
* Collapse Sidebar asset bundle
* Experimental!
*
* In your module's init() method, you can register this asset bundle like this:
* if (Craft::$app->request->isCpRequest) {
* Craft::$app->view->registerAssetBundle(CollapseSidebarAsset::class);
* }
*/
class CollapseSidebarAsset extends AssetBundle
{
public $sourcePath = __DIR__ . '/dist';
public $js = ['collapse-sidebar.js'];
public $css = ['collapse-sidebar.css'];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment