Search code examples
javascripthtmlshow-hide

Toggle show/hide functions between multiple divs


I have a page on my site which has 3 separate 'hidden' divs. Each with it's own 'show/hide' button.

  • Currently... each div and button set functions independently.
  • Therefore... if all divs are shown (open) at the same time, they stack according to their respective order.

Instead of that, I would rather restrict the function a bit, so that only div can be shown (open) at a time.

Example: If Div 1 is shown, and the user then clicks the Div 2 (or Dive 3) button, Div 1 (or which ever div is open at the time, will close.

I am not sure how to adjust my code to make that all work together. I have tried a few ideas, but they were all duds. So I posted a generic 'independent' version below.

function show_Div_1() {
  var div1 = document.getElementById("Div_1");
  if (div1.style.display === "none") {
    div1.style.display = "block";
  } else {
    div1.style.display = "none";
  }
}

function show_Div_2() {
  var div2 = document.getElementById("Div_2");
  if (div2.style.display === "none") {
    div2.style.display = "block";
  } else {
    div2.style.display = "none";
  }
}

function show_Div_3() {
  var div3 = document.getElementById("Div_3");
  if (div3.style.display === "none") {
    div3.style.display = "block";
  } else {
    div3.style.display = "none";
  }
}
.div {
  width: 270px;
  height: 30px;
  padding-left: 10px;
}
<button type="button" onclick="show_Div_1()">Div 1 - Red</button>
<button type="button" onclick="show_Div_2()" style="margin-left: 4px">Div 2 - Blue</button>
<button type="button" onclick="show_Div_3()" style="margin-left: 4px">Div 3 - Green</button>
<div id="Div_1" class="div" style="background-color:red; display: none;"></div>
<div id="Div_2" class="div" style="background-color:blue; display: none;"></div>
<div id="Div_3" class="div" style="background-color:green; display: none;"></div>


Solution

  • I would suggest using data attributes for a toggle. Why? you can use CSS for them and you can use more than just a toggle - multiple "values".

    Here in this example I do your "click" but also added a double click on the button for a third value. Try some clicks and double clicks!

    A bit of overkill perhaps but more than just "toggle" for example you could use this to show "states" of things like a stoplight or any number of things.

    Use the grid display and move them by just adding a data attribute value and double click it to get it to go (using css) to some grid-area:, things like that.

    const hideValues = {
      hide: "hidden",
      show: "showme",
      double: "dblclick"
    };
    
    function dblClickHander(event) {
      const targetSelecor = event.target.dataset.target;
      const target = document.querySelector(targetSelecor);
      const action = target.dataset.hideme == hideValues.double ? hideValues.hide : hideValues.double;
      const toggleTargets = document.querySelectorAll('.toggle-target');
      toggleTargets.forEach(el => {
        el.dataset.hideme = hideValues.hide;
      });
      target.dataset.hideme = action;
    }
    
    function toggleEventHandler(event) {
      const targetSelecor = event.target.dataset.target;
      const target = document.querySelector(targetSelecor);
      const showHide = target.dataset.hideme == hideValues.hide ? hideValues.show : hideValues.hide;
      const toggleTargets = document.querySelectorAll('.toggle-target');
      toggleTargets.forEach(el => {
        el.dataset.hideme = hideValues.hide;
      });
      target.dataset.hideme = showHide;
    }
    
    /* set up event handlers on the buttons */
    const options = {
      capture: true
    };
    /* we do this first to prevent the click from happening */
    const toggleButtons = document.querySelectorAll('.toggle-button');
    toggleButtons.forEach(el => {
      el.addEventListener('dblclick', dblClickHander, options);
    });
    toggleButtons.forEach(el => {
      el.addEventListener('click', toggleEventHandler, options)
    });
    .toggle-target {
      width: 270px;
      height: 30px;
      padding-left: 10px;
    }
    
    .toggle-target[data-hideme="hidden"] {
      display: none;
    }
    
    .toggle-target[data-hideme="showme"] {
      display: block;
    }
    
    .toggle-target[data-hideme="dblclick"] {
      display: block;
      border: solid 2px green;
      padding: 1rem;
      opacity: 0.50;
    }
    
    .red-block {
      background-color: red;
    }
    
    .blue-block {
      background-color: blue;
    }
    
    .green-block {
      background-color: green;
    }
    <button type="button" class="toggle-button" data-target=".red-block">Div 1 - Red</button>
    <button type="button" class="toggle-button" data-target=".blue-block">Div 2 - Blue</button>
    <button type="button" class="toggle-button" data-target=".green-block">Div 3 - Green</button>
    <div class="toggle-target red-block" data-hideme="hidden">red</div>
    <div class="toggle-target blue-block" data-hideme="hidden">blue</div>
    <div class="toggle-target green-block" data-hideme="hidden">green</div>