Home > Net >  Two Column Accordion with Separate Full Width Divs
Two Column Accordion with Separate Full Width Divs

Time:12-02

The intension is to have a two column accordion, without limiting the "expand" field to the left or right column. The catch is that there will be multiple on one page. This is already created, but only button 1 is working. With the way my JS is going, it will get very very repetitive - I am looking for assistance with re-writing the JS to be multiple click friendly. Fiddle: https://codepen.io/ttattini/pen/abLzaaY

EDIT: It would also be perfect if one dropdown would close as the next is opened

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="row">
  
<div id="column">
  <button id="button">I am Button #1</button>
  <button id="button">I am Button #3</button>
</div>

<div id="column">
  <button id="button">I am Button #2</button>
  <button id="button">I am Button #4</button>
</div>

</div>

 <div id="hidden">
  <p id="content"> So here I am #1</p>
</div>

 <div id="hidden">
  <p id="content"> So here I am #2</p>
</div>

<div id="hidden">
  <p id="content"> So here I am #3</p>
</div>

<div id="hidden">
  <p id="content"> So here I am #4</p>
</div>

CSS

#hidden {
  background: #ccc;
  margin-top: 2%;
  overflow: hidden;
  transition: height 200ms;
  height: 0; /* <-- set this */
}

#button {
  padding: 10px;
  margin-top: 5px;
  width:50%;
  margin-left: 10%;
  cursor: pointer;
}

#row {
   display: flex;
}
#column {
  flex: 50%;
}

JS

$(function() {
  var b = $("#button");
  var w = $("#hidden");
  var l = $("#content");

  b.click(function() {
    if (w.hasClass('open')) {
      w.removeClass('open');
      w.height(0);
    } else {
      w.addClass('open');
      w.height(l.outerHeight(true));
    }

  });
});

CodePudding user response:

The biggest issue is that you're using IDs when you should be using classes. IDs must be unique to each element in a page. When you repeat an ID, JS will only target the first element using that ID. That's why only the first one is working.

The second issue is that, because of the way the script is written, it will only target a single element. What you need to do is get all the elements you want to target by something like their class name and then loop through them, applying the event listener to each one and its appropriate children.

EDIT: Here is an example from some code I wrote for a page with multiple accordions a few weeks ago in vanilla JS

//Below I establish a counting variable and find all the accordions on the page
const acc = document.getElementsByClassName( 'accordion' );
let i;

//Looping through each accordion
for ( i = 1; i <= acc.length; i   ) {
    //Identify target for the event listener. In this case, a heading for each accordion, which I've numbered e.g. "title-1"
    const title = 'title-'   i;
    const label = document.getElementById( title );

    //Identify target content, in this case a list that has a unique ID e.g. "list-1"
    const listNum = 'list-'   i;
    const list = document.getElementById( listNum );
    //Add event listener to heading that toggles the active classes
    label.addEventListener( 'click', function() {
        label.classList.toggle( 'accordion--active' );
    });
}

Of course, there's more than one way to skin a cat, but this is a working example.

CodePudding user response:

I have tracked the clicked event of each button and showed the corresponding hidden content with the use of data- attribute.

I have used vanilla JavaScipt instead of jQuery.

const buttons = document.querySelectorAll('.button');
const hiddens = document.querySelectorAll('.hidden');

buttons.forEach((btn) => {
  btn.addEventListener('click', btnClicked)
  
  function btnClicked(e) {    
    hiddens.forEach((hidden) => {
      if(e.target.dataset.btn == hidden.dataset.content) {
        hidden.classList.toggle('height')
      } else {
        hidden.classList.remove('height')
      }
    })
}
})
.hidden {
  background: #ccc;
  margin-top: 2%;
  padding-left:2%;
  overflow: hidden;
  transition: height 200ms;
  height: 0; /* <-- set this */
}

.hidden.height {
  height: 50px;
}

.button {
  padding: 10px;
  color: white;
  background-color: #2da6b5;
  border: none;
  margin-top: 5px;
  width:90%;
  margin-left: 5%;
  cursor: pointer;
}

.button:hover {
  filter: brightness(.9);
}

#row {
   display: flex;
}
.column {
  flex: 50%;
}
<div id="row">
  
<div class="column">
  <button class="button" data-btn="one">I am Button #1</button>
  <button class="button" data-btn="three">I am Button #3</button>
</div>

<div class="column">
  <button class="button" data-btn="two">I am Button #2</button>
  <button class="button" data-btn="four">I am Button #4</button>
</div>

</div>

 <div class="hidden" data-content="one">
  <p class="content"> So here I am #1</p>
</div>

 <div class="hidden" data-content="two">
  <p class="content"> So here I am #2</p>
</div>

<div class="hidden" data-content="three">
  <p class="content"> So here I am #3</p>
</div>

<div class="hidden" data-content="four">
  <p class="content"> So here I am #4</p>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Also, please do not use the same ID at multiple elements.

CodePudding user response:

The place is for asking questions and getting answers, not for finding people who will accomplish your goals for you.

  • Related