Bootstrap 3 свернуть аккордеон: свернуть все работает, но затем не может развернуть все, сохраняя данные-родителя

Я использую Bootstrap 3 и пытаюсь настроить следующую структуру аккордеона / сворачивания:

  1. Onload: каждая аккордеонная панель в группе полностью свернута и функционирует, как задокументировано / ожидаемо.

  2. Нажатие кнопки: каждая панель аккордеона раскрывается, и нажатие переключателей не имеет никакого эффекта (включая эффекты привязки URL).

  3. Еще одно нажатие кнопки: все панели возвращаются в состояние загрузки; все свернуто и кликабельно как обычно.

Я дошел до шага 2, но когда я снова нажимаю кнопку на шаге 3, это не дает никакого эффекта. Я также не вижу ошибок консоли в Chrome Dev Tools или при запуске кода через локальный JSHint.

Я бы хотел, чтобы этот цикл повторялся каждый раз при нажатии кнопки.

Я установил свой код здесь http://bootply.com/98140 и здесь http://jsfiddle.net/A9vCx/

Мне бы хотелось знать, что я делаю не так, и я ценю предложения. Спасибо!

Мой HTML:

<button class="collapse-init">Click to disable accordion behavior</button>
<br><br>
<div class="panel-group" id="accordion">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
          Collapsible Group Item #1
        </a>
      </h4>
    </div>
    <div id="collapseOne" class="panel-collapse collapse">
      <div class="panel-body">
        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid.
      </div>
    </div>
  </div>
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">
          Collapsible Group Item #2
        </a>
      </h4>
    </div>
    <div id="collapseTwo" class="panel-collapse collapse">
      <div class="panel-body">
        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid.
      </div>
    </div>
  </div>
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree">
          Collapsible Group Item #3
        </a>
      </h4>
    </div>
    <div id="collapseThree" class="panel-collapse collapse">
      <div class="panel-body">
        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid.
      </div>
    </div>
  </div>
</div>

My JS:

$(function() {

  var $active = true;

  $('.panel-title > a').click(function(e) {
    e.preventDefault();
  });

  $('.collapse-init').on('click', function() {
    if(!$active) {
      $active = true;
      $('.panel-title > a').attr('data-toggle', 'collapse');
      $('.panel-collapse').collapse({'toggle': true, 'parent': '#accordion'});
      $(this).html('Click to disable accordion behavior');
    } else {
      $active = false;
      $('.panel-collapse').collapse({'toggle': true, 'parent': '#accordion'});
      $('.panel-title > a').removeAttr('data-toggle');
      $(this).html('Click to enable accordion behavior');
    }
  });

});

person cfx    schedule 03.12.2013    source источник


Ответы (4)


Обновленный ответ

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

Вместо этого лучшим подходом было бы:

  1. Разрешить каждой панели переключаться индивидуально
  2. Затем, при необходимости, принудительно настройте поведение аккордеона вручную.

Чтобы разрешить переключение каждой панели индивидуально, в элементе data-toggle="collapse" установите атрибут data-target на селектор .collapse идентификатора панели (вместо того, чтобы устанавливать атрибут data-parent для родительского элемента управления. Подробнее об этом можно прочитать в вопрос Измените плагин свертывания Twitter Bootstrap, чтобы аккордеоны оставались открытыми.

Примерно каждая панель должна выглядеть так:

<div class="panel panel-default">
   <div class="panel-heading">
         <h4 class="panel-title"
             data-toggle="collapse" 
             data-target="#collapseOne">
             Collapsible Group Item #1
         </h4>
    </div>
    <div id="collapseOne" 
         class="panel-collapse collapse">
        <div class="panel-body"></div>
    </div>
</div>

Чтобы вручную принудительно применить поведение аккордеона, вы можете создать обработчик для события свертывания шоу, которое происходит непосредственно перед отображением каких-либо панелей. Используйте это, чтобы убедиться, что все другие открытые панели закрываются до отображения выбранной (см. ответ на открытие нескольких панелей). Вам также нужно, чтобы код выполнялся только тогда, когда панели активны. Для этого добавьте следующий код:

$('#accordion').on('show.bs.collapse', function () {
    if (active) $('#accordion .in').collapse('hide');
});

Затем используйте show и hide для переключения видимости каждой из панелей и data-toggle для включения и отключения элементов управления.

$('#collapse-init').click(function () {
    if (active) {
        active = false;
        $('.panel-collapse').collapse('show');
        $('.panel-title').attr('data-toggle', '');
        $(this).text('Enable accordion behavior');
    } else {
        active = true;
        $('.panel-collapse').collapse('hide');
        $('.panel-title').attr('data-toggle', 'collapse');
        $(this).text('Disable accordion behavior');
    }
});

Рабочая демонстрация в jsFiddle

person KyleMit    schedule 03.12.2013
comment
Оооочень близко! Если я щелкну панель 1, затем дважды щелкните button, затем щелкните панель 1, затем щелкните панель 2, затем снова щелкните button, панель 2 скрывается и остается закрытой :-( - person cfx; 03.12.2013
comment
Также можно сломать это, загрузив свежий, затем щелкните панель 1, затем щелкните панель 2, затем щелкните панель 3, затем щелкните button и панель 3 скрываются, когда она должна отображаться. - person cfx; 03.12.2013
comment
Очень близко, и я просто хочу еще раз поблагодарить вас - я хотел бы принять оба ответа, поскольку они оба незаменимы! - person cfx; 03.12.2013
comment
@gordian, я обновил решение, которое, на мой взгляд, является самым чистым из всех предложений. Тем не менее, это была хорошая групповая работа. - person KyleMit; 03.12.2013
comment
Определенно самый чистый из двух. Спасибо и еще раз @Trevor! - person cfx; 03.12.2013
comment
Я очистил его еще немного, так как нам не нужен href Я заменил якорь переключения панели на <p>, что также означает, что мы можем удалить раздел preventDefault()! jsfiddle.net/3NuHh/2 - person cfx; 04.12.2013
comment
Я подчистил еще больше! Поскольку нам, вероятно, не нужен элемент <p>, если он единственный в panel-title jsFiddle < / b> :) - person KyleMit; 04.12.2013
comment
Проблема с этим решением: вложенные аккордеоны полностью разрушают его, потому что событие show.bs.collapse всплывает. См. сломанный jsfiddle здесь Если вы затем зарегистрируете событие show.bs.collapse на каждой сворачиваемой панели в панелях аккордеона это предотвращает образование пузырей, это все еще может работать, но у меня есть чувство, что это тоже сломает кое-что. Подробнее об этом чуть позже. - person FireSBurnsmuP; 16.10.2015
comment
@FireSBurnsmuP, я бы не сказал так много, что это недостаток этого конкретного решения, но совершенно новый вариант использования, который следует рассмотреть. Ни один фрагмент не будет работать, если вы просто скопируете макароны где-нибудь еще, но, вероятно, есть способ использовать этот процесс для вашей конкретной разметки. Он должен представлять максимально простой код, чтобы многие люди могли адаптировать его к своей конкретной ситуации. В 99% случаев все будет нормально, поэтому нет необходимости добавлять дополнительный код для гипотетического более сложного примера. - person KyleMit; 16.10.2015
comment
@KyleMit Понятно. Однако стоит отметить, что тем из нас, у кого более сложные ситуации, потребуется больше работы. - person FireSBurnsmuP; 16.10.2015
comment
@FireSBurnsmuP, с уважением, я не согласен. Я не думаю, что стоит указывать "that more work will be needed for those of us who have more complex situations". Это трюизм практически для каждого вопроса о stackoverflow. Существует бесконечное количество более сложных ситуаций, и их не следует рассматривать в вопросе или указывать в комментариях, иначе это будет очень шумно. Ответ должен направить вас на правильный путь для других реализаций. Если у вас возникли проблемы с его реализацией, это отличный повод задать новый вопрос, который объясняет, что отличается / не работает. - person KyleMit; 16.10.2015

По какой-то причине $('.panel-collapse').collapse({'toggle': true, 'parent': '#accordion'});, кажется, работает только в первый раз, и работает только для расширения разборного. (Я попытался начать с расширенного складного устройства, и он не рухнул.)

Это может быть что-то, что запускается один раз при первой инициализации collapse с этими параметрами.

Вам повезет больше, если вы воспользуетесь методами show и hide.

Вот пример:

$(function() {

  var $active = true;

  $('.panel-title > a').click(function(e) {
    e.preventDefault();
  });

  $('.collapse-init').on('click', function() {
    if(!$active) {
      $active = true;
      $('.panel-title > a').attr('data-toggle', 'collapse');
      $('.panel-collapse').collapse('hide');
      $(this).html('Click to disable accordion behavior');
    } else {
      $active = false;
      $('.panel-collapse').collapse('show');
      $('.panel-title > a').attr('data-toggle','');
      $(this).html('Click to enable accordion behavior');
    }
  });

});

http://bootply.com/98201

Обновить

Конечно, KyleMit, кажется, лучше меня справляется с этим. Я впечатлен его ответом и пониманием.

Я не понимаю, что происходит или почему show, казалось, в некоторых местах переключается.

Но после некоторого безделья ... Наконец-то пришло следующее решение:

$(function() {
  var transition = false;
  var $active = true;

  $('.panel-title > a').click(function(e) {
    e.preventDefault();
  });

  $('#accordion').on('show.bs.collapse',function(){
    if($active){
        $('#accordion .in').collapse('hide');
    }
  });

  $('#accordion').on('hidden.bs.collapse',function(){
    if(transition){
        transition = false;
        $('.panel-collapse').collapse('show');
    }
  });

  $('.collapse-init').on('click', function() {
    $('.collapse-init').prop('disabled','true');
    if(!$active) {
      $active = true;
      $('.panel-title > a').attr('data-toggle', 'collapse');
      $('.panel-collapse').collapse('hide');
      $(this).html('Click to disable accordion behavior');
    } else {
      $active = false;
      if($('.panel-collapse.in').length){
        transition = true;
        $('.panel-collapse.in').collapse('hide');       
      }
      else{
        $('.panel-collapse').collapse('show');
      }
      $('.panel-title > a').attr('data-toggle','');
      $(this).html('Click to enable accordion behavior');
    }
    setTimeout(function(){
        $('.collapse-init').prop('disabled','');
    },800);
  });
});

http://bootply.com/98239

person Trevor    schedule 03.12.2013
comment
Спасибо @Trevor. Проблема с использованием метода show заключается в том, что если вы дважды щелкните button, затем откроете панель 1, когда вы нажмете, чтобы открыть панель 2, панель 1 останется открытой, почти как будто она не помнит свою группировку. - person cfx; 03.12.2013
comment
+1 отличный ответ. Чтобы расширить необходимость использования show: когда вы вызываете collapse функцию (или любую функцию начальной загрузки), если вы передаете объект, это означает, что вы инициируете коллапс. Параметр toggle только toggles the collapsible element on invocation (из этот ответ) - person KyleMit; 03.12.2013
comment
Спасибо, @KyleMit! Я теперь намного ближе. Я добавил проверку, но теперь проблема, которую я обнаружил, заключается в том, что если вы загрузите новую скрипку, затем покажите панель 1 и щелкните button, затем панель 1 закроется (переключается) вместо того, чтобы отображаться, как остальные. bootply.com/98224 - person cfx; 03.12.2013
comment
@gordian, см. мой ответ, который должен выполнять все по мере необходимости. - person KyleMit; 03.12.2013
comment
у меня почему-то e.stopPropagation() не работает, поэтому я просто использовал return false; вместо - person Ivan; 10.02.2016

Чтобы сохранить природу аккордеона нетронутой, когда вы хотите также использовать функции «скрыть» и «показать», такие как .collapse( 'hide' ), вы должны инициализировать складные панели с родительским свойством, установленным в объекте с помощью toggle: false, прежде чем делать какие-либо вызовы для «скрыть» или «показать».

// initialize collapsible panels
$('#accordion .collapse').collapse({
  toggle: false,
  parent: '#accordion'
});

// show panel one (will collapse others in accordion)
$( '#collapseOne' ).collapse( 'show' );

// show panel two (will collapse others in accordion)
$( '#collapseTwo' ).collapse( 'show' );

// hide panel two (will not collapse/expand others in accordion)
$( '#collapseTwo' ).collapse( 'hide' );
person mike    schedule 12.05.2016

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

 $(document).ready(){
      $('#collapseSix').collapse("hide");
 }
person Sheryar Nizar    schedule 18.04.2016