Сложное поведение Bootstrap Collapse

Как реализовать сворачивание Bootstrap 4 в иерархии элементов (в моем случае панели навигации)

У меня есть следующая иерархия некоторых элементов моей страницы, и я хочу использовать поведение сворачивания в этом «дереве».

Рисунок 1

В частности, я желаю следующего поведения

(который, как я считаю, имеет смысл)

Где зеленый означает, что отображается панель навигации, а красный означает, что она свернута.

Рисунок 2

С текущим состоянием

и нажав на Вариант B1

Рисунок 3

это просто сворачивает панель навигации B1

В другом примере при нажатии на опцию A

Рисунок 4

Это показывает панель навигации A

и сворачивает всех потомков варианта B

(панель навигации B и панель навигации B1)

Рисунок 5

Правила можно свести к 3 простым правилам:

1) При нажатии на элемент с некоторыми дочерними элементами (и, возможно, другими дочерними элементами) активными (а здесь активными я имею в виду, показанными) все дочерние элементы и потомки разрушаются.

2) При нажатии на элемент X, у которого нет активных дочерних элементов, покажите (прямые) дочерние элементы X И сверните все потомки братьев и сестер X.

3) все потомки первичной навигации загружаются свернутыми

Я мог получить желаемое поведение с помощью специального кода javascript, и, к сожалению, мне пришлось игнорировать некоторые желаемые функции, уже предоставляемые плагином коллапса из начальной загрузки, и повторно реализовать их в соответствии с моими потребностями.

Перейдите сюда, чтобы получить Bootply

Вот упрощенная часть HTML

<nav id="main-nav" class="navbar navbar-expand-lg navbar-dark">
    <ul class="navbar-nav align-nav">
        <li class="nav-item">
            <a id="togglenavA" class="nav-link" href="#" data-target="#navA" aria-controls="navA" aria-expanded="false" aria-label="Toggle navigation">Option A</a>
        </li>
        <li class="nav-item">
            <a id="togglenavB" class="nav-link" href="#" data-target="#navB" aria-controls="navB" aria-expanded="false" aria-label="Toggle navigation">Option B</a>
        </li>
    </ul>
</nav>
<div id="navA" class="collapse">
    <nav id="NAVA" class="navbar navbar-expand-lg navbar-dark">
        <ul class="navbar-nav align-nav">
            <li class="nav-item">
                <a class="nav-link" href="#">Option A1</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Option A2</a>
            </li>
        </ul>
    </nav>
</div>
<div id="navB" class="collapse">
    <nav id="NAVB" class="navbar navbar-expand-lg navbar-dark">
        <ul class="navbar-nav align-nav">
            <li class="nav-item">
                <a id="togglenavB1" class="nav-link" href="#" data-target="#navB1" aria-controls="navB1" aria-expanded="false" aria-label="Toggle navigation">Option B1</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Option B2</a>
            </li>
        </ul>
    </nav>
</div>
<div id="navB1" class="collapse">
    <nav id="NAVB1" class="navbar navbar-expand-lg navbar-dark">
        <ul class="navbar-nav align-nav">
            <li class="nav-item">
                <a class="nav-link" href="#">Option B1.1</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Option B1.2</a>
            </li>
        </ul>
    </nav>
</div>

И вот Javascript, который повторно реализует стиль аккордеона, но с дополнительным коллапсом дочерних элементов брата и сестры.

$(document).ready(function() {
    $('#togglenavA').click(function() {
        $('#navB').collapse('hide')
        $('#navB1').collapse('hide')
        $('#navA').collapse('toggle')
        $('#navA').on('hidden.bs.collapse', function () {
            $('#togglenavA').attr("aria-expanded","false");
        }) // for screen readers purpose
        $('#navA').on('shown.bs.collapse', function () {
            $('#togglenavA').attr("aria-expanded","true");
        })
    });
    $('#togglenavB').click(function() {
        $('#navA').collapse('hide')
        $('#navB1').collapse('hide')
        $('#navB').collapse('toggle')
        $('#navB').on('hidden.bs.collapse', function () {
            $('#togglenavB').attr("aria-expanded","false");
        })
        $('#navB').on('shown.bs.collapse', function () {
            $('#togglenavB').attr("aria-expanded","true");
        })
    });
    $('#togglenavB1').click(function() {
        $('#navB1').collapse('toggle')
        $('#navB1').on('hidden.bs.collapse', function () {
            $('#togglenavB1').attr("aria-expanded","false");
        })
        $('#navB1').on('shown.bs.collapse', function () {
            $('#togglenavB1').attr("aria-expanded","true");
        })
    });
});

Примечание: хотя это решение решает мою проблему, оно делает это за счет игнорирования уже реализованной в Bootstrap аккордеона и удаления некоторых атрибутов данных из некоторых ссылок, чтобы избежать конфликтов между некоторыми автоматическими функциями плагина с моим пользовательским кодом.


person gota    schedule 06.09.2017    source источник
comment
Вы не можете ожидать в ответе никакого пользовательского javascript, так как это может быть ошибочная реализация начальной загрузки 4. Кроме того, вы сами не продемонстрировали никаких попыток, неплохо было бы попробовать какой-нибудь html-код, который вы пробовали.   -  person Deckerz    schedule 08.09.2017
comment
Вам нужно продемонстрировать некоторые исследовательские усилия или какой-то код, который вы пробовали.   -  person JohanSellberg    schedule 08.09.2017
comment
Вы оба правы! Я уже провел небольшое исследование и придумал собственный код, который будет работать. Ищу более принципиальный способ сделать это   -  person gota    schedule 08.09.2017
comment
Спасибо за отрицательные голоса! Это всегда делает меня лучше   -  person gota    schedule 08.09.2017
comment
Я предлагаю использовать скрипку или обновить ваш вопрос ответом, который вы дали, который покажет ваши усилия, и я с радостью уберу свой -1 до +1. Показывает, что вы пробовали использовать cusom, но не нашли. собственный javascript.   -  person JohanSellberg    schedule 08.09.2017
comment
Я не верю, что есть способ сделать это без специального JavaScript. Однако я считаю, что есть простой способ сделать это с помощью Bootstrap Collapse API (который я считаю лучшей практикой). Я только колеблюсь при публикации, поскольку он не выполняет ожидания без пользовательского javascript.   -  person inki    schedule 14.09.2017


Ответы (2)


Рабочий пример Bootply

Мой подход предполагает следующие обновления:


1. Включите отсутствующий атрибут в свои ссылки (<a>)

Добавьте атрибут data-toggle="collapse" к ссылкам меню. Это даст вам ожидаемое поведение Bootstrap при сворачивании. Пример:

<a id="togglenavA" class="nav-link" href="#" data-toggle="collapse" data-target="#navA" aria-controls="navA" aria-expanded="false" aria-label="Toggle navigation">Option A</a>

2. Добавьте второй класс collapse-child

Это позволяет нам настроить таргетинг на эти дочерние панели навигации. Пример:

<div id="navA" class="collapse collapse-child">

3. JavaScript

Затем JavaScript можно упростить до следующего фрагмента:

$(document).ready(function() {
  var hideChildren = function() {
    $('div.collapse-child').collapse('hide');
  };

  $('a.nav-link:not([aria-controls])').click(function(el){
    hideChildren();
  });

  $('#main-nav a').click(function(){
    hideChildren();
  });
});

Я не уверен, что это соответствует вашему требованию «без специального Javascript», но я считаю, что это лучший способ достижения этого с самой последней версией Bootstrap4.

person inki    schedule 14.09.2017
comment
Круто! Я думаю, у вас есть ненужный код, а именно $ ('# navA'). On ('show.bs.collapse', function () {$ ('# navB'). Collapse ('hide');}); $ ('# navB'). on ('show.bs.collapse', function () {$ ('# navA'). collapse ('скрыть');}); Похоже, вы хотите реализовать стиль аккордеона, но он уже есть! См. Эту вилку. bootply.com/hUC5aXD5AF# Не могли бы вы заменить ссылку на эту? - person gota; 15.09.2017
comment
Ага, ты прав. Осталось с моей первой попытки. Я редактировал JS и ссылку на рабочий пример Bootply. - person inki; 15.09.2017

Хорошо, я нашел способ сделать это с помощью специального кода javascript и игнорирования некоторых желаемых функций, предоставляемых плагином коллапса из начальной загрузки, и их повторной реализации в соответствии с моими потребностями.

Вот упрощенная часть HTML

<nav id="main-nav" class="navbar navbar-expand-lg navbar-dark">
    <ul class="navbar-nav align-nav">
        <li class="nav-item">
            <a id="togglenavA" class="nav-link" href="#" data-target="#navA" aria-controls="navA" aria-expanded="false" aria-label="Toggle navigation">Option A</a>
        </li>
        <li class="nav-item">
            <a id="togglenavB" class="nav-link" href="#" data-target="#navB" aria-controls="navB" aria-expanded="false" aria-label="Toggle navigation">Option B</a>
        </li>
    </ul>
</nav>
<div id="navA" class="collapse">
    <nav id="NAVA" class="navbar navbar-expand-lg navbar-dark">
        <ul class="navbar-nav align-nav">
            <li class="nav-item">
                <a class="nav-link" href="#">Option A1</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Option A2</a>
            </li>
        </ul>
    </nav>
</div>
<div id="navB" class="collapse">
    <nav id="NAVB" class="navbar navbar-expand-lg navbar-dark">
        <ul class="navbar-nav align-nav">
            <li class="nav-item">
                <a id="togglenavB1" class="nav-link" href="#" data-target="#navB1" aria-controls="navB1" aria-expanded="false" aria-label="Toggle navigation">Option B1</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Option B2</a>
            </li>
        </ul>
    </nav>
</div>
<div id="navB1" class="collapse">
    <nav id="NAVB1" class="navbar navbar-expand-lg navbar-dark">
        <ul class="navbar-nav align-nav">
            <li class="nav-item">
                <a class="nav-link" href="#">Option B1.1</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Option B1.2</a>
            </li>
        </ul>
    </nav>
</div>

И вот Javascript, который повторно реализует стиль аккордеона, но с дополнительным коллапсом дочерних элементов брата и сестры.

$(document).ready(function() {
    $('#togglenavA').click(function() {
        $('#navB').collapse('hide')
        $('#navB1').collapse('hide')
        $('#navA').collapse('toggle')
        $('#navA').on('hidden.bs.collapse', function () {
            $('#togglenavA').attr("aria-expanded","false");
        }) // for screen readers purpose
        $('#navA').on('shown.bs.collapse', function () {
            $('#togglenavA').attr("aria-expanded","true");
        })
    });
    $('#togglenavB').click(function() {
        $('#navA').collapse('hide')
        $('#navB1').collapse('hide')
        $('#navB').collapse('toggle')
        $('#navB').on('hidden.bs.collapse', function () {
            $('#togglenavB').attr("aria-expanded","false");
        })
        $('#navB').on('shown.bs.collapse', function () {
            $('#togglenavB').attr("aria-expanded","true");
        })
    });
    $('#togglenavB1').click(function() {
        $('#navB1').collapse('toggle')
        $('#navB1').on('hidden.bs.collapse', function () {
            $('#togglenavB1').attr("aria-expanded","false");
        })
        $('#navB1').on('shown.bs.collapse', function () {
            $('#togglenavB1').attr("aria-expanded","true");
        })
    });
});

Примечание: хотя это решение решает мою проблему, оно делает это за счет игнорирования уже реализованной в Bootstrap аккордеона и удаления некоторых атрибутов данных из некоторых ссылок, чтобы избежать конфликтов между некоторыми автоматическими функциями плагина с моим пользовательским кодом.

person gota    schedule 08.09.2017