Автоматическое нажатие соответствующей кнопки, при нажатии на ссылку

Что то вроде панели быстрого доступа, с кучей папок, внутри которых плейлисты. При клике на название папки - перекидывает в неё, при клике на стрелочку - выпадающее меню с содержимым.

введите сюда описание изображения

Подскажите пожалуйста, как сделать так, что бы при клике на название папки ещё и всегда автоматически кликалась стрелочка соответствующей папки, что бы происходило её раскрытие?

введите сюда описание изображения введите сюда описание изображения

Всё это HTML кодом:

<div class="os-host os-host-foreign os-theme-spotify os-host-resize-disabled os-host-scrollbar-horizontal-hidden main-rootlist-rootlistPlaylistsScrollNode os-host-transition os-host-overflow os-host-overflow-y">
  <div class="os-resize-observer-host observed">
    <div class="os-resize-observer" style="left: 0px; right: auto;"></div>
  </div>
  <div class="os-size-auto-observer observed" style="height: calc(100% + 1px); float: left;">
    <div class="os-resize-observer"></div>
  </div>
  <div class="os-content-glue" style="margin: -8px 0px; width: 210px; height: 514px;"></div>
  <div class="os-padding">
    <div class="os-viewport os-viewport-native-scrollbars-invisible" style="overflow-y: scroll;">
      <div class="os-content" style="padding: 8px 0px; height: 100%; width: 100%;">
        <ul tabindex="0">
          <li class="GlueDropTarget GlueDropTarget--playlists GlueDropTarget--folders GlueDropTarget--tracks GlueDropTarget--albums GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
            <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:0;" aria-expanded="false"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/folder/cf24d98bbd2a76b3"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">New Folder</span></a>
              <button
                tabindex="-1" class="spoticon-chart-down-16 main-rootlist-expandArrow"></button>
            </div>
          </li>
          <li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
            <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:0;" aria-expanded="false"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/5y4StXSisfRVcsxWrdOqkv"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">New Playlist</span></a>
              <div
                class="main-rootlist-statusIcons"></div>
      </div>
      </li>
      <li class="GlueDropTarget GlueDropTarget--playlists GlueDropTarget--folders GlueDropTarget--tracks GlueDropTarget--albums GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
        <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:0;" aria-expanded="false"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/folder/bb7db111531df4e6"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Test12</span></a><button tabindex="-1"
            class="spoticon-chart-down-16 main-rootlist-expandArrow main-rootlist-expandArrowRotated"></button></div>
      </li>
      <li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
        <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/4xpdNtqq6L6Lw7Vfb1DEKx"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Playlist123</span></a>
          <div
            class="main-rootlist-statusIcons"></div>
    </div>
    </li>
    <li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
      <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/5x6R3crqMuR9BtUKYOTSZC"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Playlist1</span></a>
        <div
          class="main-rootlist-statusIcons"></div>
  </div>
  </li>
  <li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
    <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:0;" aria-expanded="false"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/5Mr4mljepnnzLZtbEtFU38"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Playlist without folder</span></a>
      <div
        class="main-rootlist-statusIcons"></div>
</div>
</li>
<li class="GlueDropTarget GlueDropTarget--playlists GlueDropTarget--folders GlueDropTarget--tracks GlueDropTarget--albums GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:0;" aria-expanded="false"><a aria-current="page" class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink main-rootlist-rootlistItemLinkActive" draggable="false" tabindex="-1" href="/folder/123456789"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Folder2</span></a>
    <button
      tabindex="-1" class="spoticon-chart-down-16 main-rootlist-expandArrow"></button>
  </div>
</li>
<li class="GlueDropTarget GlueDropTarget--playlists GlueDropTarget--folders GlueDropTarget--tracks GlueDropTarget--albums GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:0;" aria-expanded="false"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/folder/42f7e898ec18ce18"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Folder1</span></a><button tabindex="-1"
      class="spoticon-chart-down-16 main-rootlist-expandArrow main-rootlist-expandArrowRotated"></button></div>
</li>
<li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;" aria-expanded="false"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/2ga8pLCNCQKwRKtvgsyeuh"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Playlist1</span></a>
    <div class="main-rootlist-statusIcons"></div>
  </div>
</li>
<li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;" aria-expanded="false"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/6etMctepmc5jnvo1ZBoooK"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Playlist2</span></a>
    <div class="main-rootlist-statusIcons"></div>
  </div>
</li>
<li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;" aria-expanded="false"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/1WuqEzoJwEHZLUAin9Sbhz"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Playlist3</span></a>
    <div class="main-rootlist-statusIcons"></div>
  </div>
</li>
<li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;" aria-expanded="false"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/2RjKE10fckSMRsxzxOgkCb"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Playlist3</span></a>
    <div class="main-rootlist-statusIcons"></div>
  </div>
</li>
<li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/71WxDQvgE5keveEP8C5XQu"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Новый плейлист</span></a>
    <div
      class="main-rootlist-statusIcons"></div>
  </div>
</li>
<li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/1rdfLI4EJpLR0OOw75jqkJ"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Новый плейлист</span></a>
    <div
      class="main-rootlist-statusIcons"></div>
  </div>
</li>
<li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/47umOtTkjYM4JtR1yRkLQR"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Новый плейлист</span></a>
    <div
      class="main-rootlist-statusIcons"></div>
  </div>
</li>
<li class="GlueDropTarget GlueDropTarget--albums GlueDropTarget--tracks GlueDropTarget--episodes GlueDropTarget--playlists GlueDropTarget--folders">
  <div class="main-rootlist-rootlistItem" draggable="true" style="--indentation:1;"><a class="standalone-ellipsis-one-line main-rootlist-rootlistItemLink" draggable="false" tabindex="-1" href="/playlist/7mRpNzMxDO7oEDD8AIMGhE"><span class="main-rootlist-textWrapper main-type-viola" as="span" dir="auto">Новый плейлист</span></a>
    <div
      class="main-rootlist-statusIcons"></div>
  </div>
</li>
</ul>
<div class="main-rootlist-dropIndicator" style="display: none; top: 1352px; --indentation:1;"></div>
</div>
</div>
</div>
<div class="os-scrollbar os-scrollbar-horizontal os-scrollbar-unusable">
  <div class="os-scrollbar-track">
    <div class="os-scrollbar-handle" style="width: 100%; transform: translate(0px, 0px);"></div>
  </div>
</div>
<div class="os-scrollbar os-scrollbar-vertical">
  <div class="os-scrollbar-track">
    <div class="os-scrollbar-handle" style="height: 99.0385%; transform: translate(0px, 0px);"></div>
  </div>
</div>
<div class="os-scrollbar-corner"></div>
</div>

P.S. Не знаю, возможно ли, просто идея. Может быть что то при помощи CSS? Расширить область нажатия стрелок так, что бы при клике на название, ещё и стрелка нажималась. Но всё, что я пробовал - переносило/сокращало названия папок.


Ответы (1 шт):

Автор решения: Алексей Шиманский

Первый же пример на https://www.w3schools.com/howto/howto_js_dropdown_sidenav.asp

/* Loop through all dropdown buttons to toggle between hiding and showing its dropdown content - This allows the user to have multiple dropdowns without any conflict */
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;

for (i = 0; i < dropdown.length; i++) {
    dropdown[i].addEventListener("click", function() {
        this.classList.toggle("active");
        var dropdownContent = this.nextElementSibling;
        if (dropdownContent.style.display === "block") {
            dropdownContent.style.display = "none";
        } else {
            dropdownContent.style.display = "block";
        }
    });
}
body {
  font-family: "Lato", sans-serif;
}


/* Fixed sidenav, full height */

.sidenav {
  height: 100%;
  width: 200px;
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  background-color: #111;
  overflow-x: hidden;
  padding-top: 20px;
}


/* Style the sidenav links and the dropdown button */

.sidenav a,
.dropdown-btn {
  padding: 6px 8px 6px 16px;
  text-decoration: none;
  font-size: 20px;
  color: #818181;
  display: block;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
  cursor: pointer;
  outline: none;
}


/* On mouse-over */

.sidenav a:hover,
.dropdown-btn:hover {
  color: #f1f1f1;
}


/* Main content */

.main {
  margin-left: 200px;
  /* Same as the width of the sidenav */
  font-size: 20px;
  /* Increased text to enable scrolling */
  padding: 0px 10px;
}


/* Add an active class to the active dropdown button */

.active {
  background-color: green;
  color: white;
}


/* Dropdown container (hidden by default). Optional: add a lighter background color and some left padding to change the design of the dropdown content */

.dropdown-container {
  display: none;
  background-color: #262626;
  padding-left: 8px;
}


/* Optional: Style the caret down icon */

.fa-caret-down {
  float: right;
  padding-right: 8px;
}


/* Some media queries for responsiveness */

@media screen and (max-height: 450px) {
  .sidenav {
    padding-top: 15px;
  }
  .sidenav a {
    font-size: 18px;
  }
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">


<div class="sidenav">
  <a href="#about">About</a>
  <a href="#services">Services</a>
  <a href="#clients">Clients</a>
  <a href="#contact">Contact</a>
  <button class="dropdown-btn">Dropdown 
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-container">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>
  <a href="#contact">Search</a>
</div>

<div class="main">
  <h2>Sidebar Dropdown</h2>
  <p>Click on the dropdown button to open the dropdown menu inside the side navigation.</p>
  <p>This sidebar is of full height (100%) and always shown.</p>
  <p>Some random text..</p>
</div>

Суть сводится к тому, чтобы взять все "корневые элементы" (или элементы, которые будут раскрываться) и в цикле сделать следующее:

  • элементу по которому кликнули убрать/добавить класс active
  • следующий за ним блок скрыть/показать, в зависимости от того, в каком он был состоянии до этого.

Общая модернизация может состоять в том, что менять будет достаточно класс active, а в CSS прописать зависимость подблока от активности основного:

let dropdown = Array.from(document.getElementsByClassName("dropdown-btn"));
dropdown.forEach(elem => {
    elem.addEventListener("click", () => {
        elem.classList.toggle("active");
    });
});
.dropdown-btn + .dropdown-container {
    display: none;
}

.dropdown-btn.active + .dropdown-container {
    display: block;
}

/* ОСТАЛЬНЫЕ СТИЛИ ДЛЯ ТЕКУЩЕГО ПРИМЕРА */
body {
  font-family: "Lato", sans-serif;
}

.sidenav {
  height: 100%;
  width: 200px;
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  background-color: #111;
  overflow-x: hidden;
  padding-top: 20px;
}

.sidenav a,
.dropdown-btn {
  padding: 6px 8px 6px 16px;
  text-decoration: none;
  font-size: 20px;
  color: #818181;
  display: block;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
  cursor: pointer;
  outline: none;
}

.sidenav a:hover,
.dropdown-btn:hover {
  color: #f1f1f1;
}

.main {
  margin-left: 200px;
  /* Same as the width of the sidenav */
  font-size: 20px;
  /* Increased text to enable scrolling */
  padding: 0px 10px;
}

.active {
  background-color: green;
  color: white;
}

.dropdown-container {
  display: none;
  background-color: #262626;
  padding-left: 8px;
}

.fa-caret-down {
  float: right;
  padding-right: 8px;
}


@media screen and (max-height: 450px) {
  .sidenav {
    padding-top: 15px;
  }
  .sidenav a {
    font-size: 18px;
  }
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">


<div class="sidenav">
  <a href="#about">About</a>
  <button class="dropdown-btn">Test 
    <i class="fa fa-caret-down"></i>
  </button>
   <div class="dropdown-container">
    <a href="#">Test 1</a>
    <a href="#">Test 2</a>
  </div>
  <a href="#clients">Clients</a>
  <a href="#contact">Contact</a>
  <button class="dropdown-btn">Dropdown 
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-container">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>  
  <button class="dropdown-btn">SomethingElse 
    <i class="fa fa-caret-down"></i>
  </button>
   <div class="dropdown-container">
    <a href="#">SomethingElse 1</a>
    <a href="#">SomethingElse 2</a>
    <a href="#">SomethingElse 3</a>
  </div>
</div>

<div class="main">
  <h2>Sidebar Dropdown</h2>
  <p>Click on the dropdown button to open the dropdown menu inside the side navigation.</p>
  <p>This sidebar is of full height (100%) and always shown.</p>
  <p>Some random text..</p>
</div>

Всё теперь упирается в ваше собственное знание вашей разметки и CSS чтобы адаптировать пример под себя


P.S. Да, можно это сделать на чистом CSS, но это не ко мне ?


Чистый CSS

Взято с https://stackoverflow.com/a/56607735/6104996

/* define a fixed width for the entire menu */

.navigation {
  width: 300px;
}


/* reset our lists to remove bullet points and padding */

.mainmenu,
.submenu {
  list-style: none;
  padding: 0;
  margin: 0;
}


/* make ALL links (main and submenu) have padding and background color */

.mainmenu a,
.mainmenu label {
  display: block;
  background-color: #CCC;
  text-decoration: none;
  padding: 10px;
  color: #000;
}

.mainmenu input {
  display: none;
}


/* add hover behaviour */

.mainmenu a:hover {
  background-color: #C5C5C5;
}


/* when hovering over a .mainmenu item,
  display the submenu inside it.
  we're changing the submenu's max-height from 0 to 200px;
*/

.mainmenu :checked+.submenu {
  display: block;
  max-height: 200px;
}


/*
  we now overwrite the background-color for .submenu links only.
  CSS reads down the page, so code at the bottom will overwrite the code at the top.
*/

.submenu a {
  background-color: #ddd;
}


/* hover behaviour for links inside .submenu */

.submenu a:hover {
  background-color: #993;
}


/* this is the initial state of all submenus.
  we set it to max-height: 0, and hide the overflowed content.
*/

.submenu {
  overflow: hidden;
  max-height: 0;
  -webkit-transition: all 0.5s ease-out;
}
<nav class="navigation">
  <ul class="mainmenu">
    <li><a href="">Home</a></li>
    <li><a href="">About</a></li>
    <li><label for="products">Products</label><input type="checkbox" id="products">
      <ul class="submenu">
        <li><a href="">Tops</a></li>
        <li><a href="">Bottoms</a></li>
        <li><a href="">Footwear</a></li>
      </ul>
    </li>
    <li><a href="">Contact us</a></li>
  </ul>
</nav>

Суть тут в том, что ставится невидимый input с типом checkbox и используется его свойство :checked вкупе всё с тем же селектором + который отвечает за элемент, стоЯщий сразу за текущим.

→ Ссылка