2

I have accordion buttons that I need to change based on accordion state (show, hide). I can do it no problem with click event but I would like to bind it to the state of the accordion

I tried adding an event handler to the accordion function I have written but I must be doing it incorrectly

var accordionBtn = $('.accordion-btn');
var bedAccordion = $('.accordion');

$(document).ready(function() {
  $(bedAccordion).on('show.bs.collapse', function() {
    $(this).find('i').removeClass('fa-plus');
    $(this).find('i').addClass('fa-minus');
    $('.collapse').collapse('hide');
  });

  $(bedAccordion).on('hide.bs.collapse', function() {
    $(this).find('i').removeClass('fa-minus');
    $(this).find('i').addClass('fa-plus');
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>

<div class="accordion">
  <button class="btn accordion-btn button--arrow-right" type="button" data-toggle="collapse" data-target="#bedAccordion1" aria-expanded="false" aria-controls="bedAccordion1"><i class="fas fa-plus"></i></button>
  <span class="title-3">Test</span>
  <div class="col collapse-content">
    <div class="collapse multi-collapse" id="bedAccordion1">
      <div class="border--left">
        <p><b>Test</b><sup>1</sup><br> Test
        </p>
        <p>test<br> test
        </p>
        <p><b>test</b><sup>1</sup><br> Test</p>
      </div>
    </div>
  </div>
</div>

I'd like to bind this event below to the above function so the changes happen on show and hide collapse

    $(accordionBtn).click(function () {
        $(this).toggleClass('accordion-btn--open');
        $(this).toggleClass('button--arrow-right');
    });
});

bind the button toggle class to the state of the accordion and functions above

Nidhin Joseph
  • 9,981
  • 4
  • 26
  • 48
hendy0817
  • 979
  • 2
  • 20
  • 47
  • can you share the HTML code as well please? – Nidhin Joseph Aug 23 '19 at 23:15
  • @NidhinJoseph added html..thank you :) – hendy0817 Aug 23 '19 at 23:36
  • 1
    Off topic, but you don't need to do `$(bedAccordion)` since you've already made `bedAccordion` a jQuery object. – Lee Taylor Aug 23 '19 at 23:44
  • 1
    what exactly is `bind the button toggle class to the state of the accordion` ?? – Nidhin Joseph Aug 23 '19 at 23:46
  • I may be wording it incorrect. Sorry. I’d like the toggle class for the button to fire when the accordion opens and closes. before I had an onClick on the button but I need it to change based on the accordion being opened or closed if that makes sense. Thanks again – hendy0817 Aug 23 '19 at 23:48
  • And you can also chain your calls so you don't have to create the jQuery object and find the element each time: `$(this).find('i').removeClass('fa-minus').addClass('fa-plus');` – msg Aug 23 '19 at 23:58
  • @hendy0817 from what I understand is, you need to call `toggleButton` and bind the scope on accordion click. I have answered it. – Nidhin Joseph Aug 24 '19 at 00:03
  • @NidhinJoseph this is great but not what I was after. I am trying to target the ".accordion-btn" so when the user opens one of the accordions it removes the buttons current styles and adds the new class / styles for each button, like an "active" state. then when the accordion closes it returns back to the original state. I had it working on a click event but it was changing each button at the same time. I'm trying to get only the one open to change. – hendy0817 Aug 24 '19 at 00:12
  • so you mean, have multiple accordions, and then change button style of the particular accordion when opened? – Nidhin Joseph Aug 24 '19 at 00:14
  • exactly! :)...there is actually 3 accordion panels. so user clicks open one and the button changes style and adds the minus class along with other "active" styles, which is already working. Now when they click another accordion button the current active one closes and returns back to it's original closed style – hendy0817 Aug 24 '19 at 00:17
  • @hendy0817 yep, have edited my code. – Nidhin Joseph Aug 24 '19 at 00:22
  • 1
    @NidhinJoseph you rock! thanks again!!! – hendy0817 Aug 24 '19 at 00:35

2 Answers2

4

You need to call the toggleButton with call method to set the this value.

More on Javascript call() & apply() vs bind()

var accordionBtn = $('.accordion-btn');
var bedAccordion = $('.accordion');

$(document).ready(function() {
  $(bedAccordion).on('show.bs.collapse', function(e) {
    toggleButton.call(this);
    $(this).find('.collapse').collapse('hide');
  });

  $(bedAccordion).on('hide.bs.collapse', function() {
    toggleButton.call(this);
  });
});

function toggleButton() {
  $(this).find('i').toggleClass('fa-plus').toggleClass('fa-minus');
  $(this).find('button').toggleClass('active');
}
button.active {
  background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>

<div class="accordion">
  <button class="btn accordion-btn button--arrow-right" type="button" data-toggle="collapse" data-target="#bedAccordion1" aria-expanded="false" aria-controls="bedAccordion1"><i class="fas fa-plus"></i></button>
  <span class="title-3">Test 1</span>
  <div class="col collapse-content">
    <div class="collapse multi-collapse" id="bedAccordion1">
      <div class="border--left">
        <p><b>Test</b><sup>1</sup><br> Test
        </p>
        <p>test<br> test
        </p>
        <p><b>test</b><sup>1</sup><br> Test</p>
      </div>
    </div>
  </div>
</div>

<div class="accordion">
  <button class="btn accordion-btn button--arrow-right" type="button" data-toggle="collapse" data-target="#bedAccordion2" aria-expanded="false" aria-controls="bedAccordion2"><i class="fas fa-plus"></i></button>
  <span class="title-3">Test 2</span>
  <div class="col collapse-content">
    <div class="collapse multi-collapse" id="bedAccordion2">
      <div class="border--left">
        <p><b>Test</b><sup>1</sup><br> Test
        </p>
        <p>test<br> test
        </p>
        <p><b>test</b><sup>1</sup><br> Test</p>
      </div>
    </div>
  </div>
</div>
Nidhin Joseph
  • 9,981
  • 4
  • 26
  • 48
1

In order to have just one accordion open at a time, you can use the parent attribute provided by bootstrap, you just need to provide a wrapper element for your accordions. This also allows to have multiple accordion groups so you can have one accordion active per group.

To change the icons, just define a function and pass it as the callback for the event, jQuery will take care of binding this to the current element.

var accordionBtn = $('.accordion-btn');
var bedAccordion = $('.accordion');

function toggleButton() {
  $(this).find('i').toggleClass('fa-plus').toggleClass('fa-minus');
}

$(document).ready(function() {
  bedAccordion.on('show.bs.collapse', toggleButton)
    .on('hide.bs.collapse', toggleButton);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>

<!-- Add wrapper element -->
<div id="accordion-container">
  <div class="accordion">
    <button class="btn accordion-btn button--arrow-right" type="button" data-toggle="collapse" data-target="#bedAccordion1" aria-expanded="false" aria-controls="bedAccordion1"><i class="fas fa-plus"></i></button>
    <span class="title-3">Test</span>
    <div class="col collapse-content">
      <div class="collapse multi-collapse" id="bedAccordion1" data-parent="#accordion-container">
        <div class="border--left">
          <p><b>Test</b><br>Test</p>
          <p><b>test</b><sup>1</sup><br> Test</p>
        </div>
      </div>
    </div>
  </div>
  <div class="accordion">
    <button class="btn accordion-btn button--arrow-right" type="button" data-toggle="collapse" data-target="#bedAccordion2" data-parent="#accordion-container" aria-expanded="false" aria-controls="bedAccordion1"><i class="fas fa-plus"></i></button>
    <span class="title-3">Test</span>
    <div class="col collapse-content">
      <!-- Add the data-parent to indicate which group this accordion belongs to -->
      <div class="collapse multi-collapse" id="bedAccordion2" data-parent="#accordion-container">
        <div class="border--left">
          <p><b>Test</b><br> Test</p>
          <p><b>test</b><sup>2</sup><br> Test</p>
        </div>
      </div>
    </div>
  </div>
</div>
msg
  • 7,863
  • 3
  • 14
  • 33