Patrick Ben
Patrick Ben

Reputation: 81

Hiding DIVS when clicking button

I managed to do something by searching for some javascript code that I could adapt, and I somehow made it; but its not working properly.

When the button is clicked once it works as intended, but when its clicked two times in a row, the result is inverted in a layout crash that causes two divs to be shown instead of hidden.

Here goes the demo: https://jsfiddle.net/ab8b7g4w/

HTML CODE

<input id="hideshow" type="button" value="Button one" />
<input id="hideshow2" type="button" value="Button two" />
<input id="hideshow3" type="button" value="Button third" />

<div id="punto1">
Main content
</div>

<div id="punto2">
Second div
</div>

<div id="punto3">
Third div
</div>

JQUERY CODE

jQuery(document).ready(function(){
        jQuery('#hideshow').on('click', function(event) {        
             jQuery('#punto1').toggle('show');
             jQuery('#punto2').toggle('hide');
             jQuery('#punto3').toggle('hide');
        });
    });

jQuery(document).ready(function(){
        jQuery('#hideshow2').on('click', function(event) {      
             jQuery('#punto1').toggle('hide');
             jQuery('#punto2').toggle('show');
             jQuery('#punto3').toggle('hide');
        });
    });

jQuery(document).ready(function(){
        jQuery('#hideshow3').on('click', function(event) {      
             jQuery('#punto1').toggle('hide');
             jQuery('#punto2').toggle('hide');
             jQuery('#punto3').toggle('show');
        });
    });

CSS CODE

#punto2, #punto3 { display: none; }

Is there any way to fix this thing with the double click on buttons?

Thanks so much

Upvotes: 0

Views: 79

Answers (4)

Lex
Lex

Reputation: 5014

I wouldn't use two classes show and hide. I find it adds confusion. I'd pick a state thats default either displayed or hidden. And add or remove a class when needed. In the example below the default state is to display and a class is added to the other elements making them hidden.

Secondly I wouldn't use CSS id. Use classes. This is more flexible. If you ever need to add or remove a slide you can just update the mark up without touching the js. In the example below if another button and div are added, it'll just work (providing they're added in the same position)

The magic here is finding the index of the element clicked, to know which slide index to display.

const index = buttonsArray.findIndex(el => el === clickedEl);
...
divsArray[index].className = "image-container";

The below example is written without jquery. But feel free to mix in jquery as tasks like toggling will be easier. I find things less confusing to first understand without any libraries, then add helper functions like toggle or $('.image-button')'.

<button class="image-button">One</button>
<button class="image-button">Two</button>
<button class="image-button">Three</button>
<button class="image-button">Four</button>

<div class="image-container">One</div>
<div class="image-container image-hidden">Two</div>
<div class="image-container image-hidden">Three</div>
<div class="image-container image-hidden">Four</div>

<script>

const buttons = document.querySelectorAll('.image-button');
const buttonsArray = Array.from(buttons); // convert to array to make findIndex available
const divs = document.querySelectorAll('.image-container');
const divsArray = Array.from(divs); // convert to array to make findIndex available

function handleClick(e) {
  const clickedEl = e.target;

  // find the index of the clicked button
  const index = buttonsArray.findIndex(el => el === clickedEl);

  // hide all divs
  divsArray.forEach((el) => {
    el.className = "image-container image-hidden";
  });

  // reveal the corresponding div
  divsArray[index].className = "image-container";
  console.log('click handled', index);
}

buttonsArray.forEach(el => {
  el.addEventListener('click', handleClick);
});

</script>

<style>
.image-container {
  background: orange;
  width: 100px;
  height: 100px;
}
.image-hidden {
  display: none;
}
</style>

Upvotes: 0

HyperTextCoffeePot
HyperTextCoffeePot

Reputation: 448

This solution works:

jQuery(document).ready(function(){
    jQuery('#hideshow').on('click', function(event) {        
        jQuery('#punto1').show();
        jQuery('#punto2').hide();
        jQuery('#punto3').hide();
    });
});

jQuery(document).ready(function(){
    jQuery('#hideshow2').on('click', function(event) {      
        jQuery('#punto1').hide();
        jQuery('#punto2').show();
        jQuery('#punto3').hide();
    });
});

jQuery(document).ready(function(){
    jQuery('#hideshow3').on('click', function(event) {      
        jQuery('#punto1').hide();
        jQuery('#punto2').hide();
        jQuery('#punto3').show();
    });
});

But, it won't easily scale. As you add more and more elements you're going to bloat your javascript file unnecessarily.

You might want to try using a data value to specify the element that should be shown. This way you could easily loop through an image count and reuse the code for every single image. Something like this:

<input class="hideshow" type="button" value="Button one" data-button-id="1"/>
<input class="hideshow" type="button" value="Button two" data-button-id="2"/>
<input class="hideshow" type="button" value="Button third" data-button-id="3"/>

<div id="punto1" class="image-container">
    Main content
</div>

<div id="punto2" class="image-container">
    Second div
</div>

<div id="punto3" class="image-container">
    Third div
</div>

The JS:

jQuery(document).ready(function(){
    jQuery('.hideshow').on('click', function(event) {   
        var buttonID = this.dataset.buttonId;
        var containerID = "#punto" + buttonID;
        //Close all open containers
        jQuery(".image-container").hide();
        jQuery(containerID).show();
    });
});

And of course the CSS:

#punto2, #punto3 { display: none; }

You can try it out here: https://jsfiddle.net/ab8b7g4w/1/

Upvotes: 0

Abderrahman Hilali
Abderrahman Hilali

Reputation: 221

just change the toggle with hide or show functions.

the toggle function you have used right there will toggle between the hidden and shown states, so when you click the first the div is hidden and the two other divs are shown, and when you click the second time the first div will be shown and the two others will be hidden...

jQuery(document).ready(function(){
    jQuery('#hideshow').on('click', function(event) {        
         jQuery('#punto1').show();
         jQuery('#punto2').hide();
         jQuery('#punto3').hide();
    });
});

jQuery(document).ready(function(){
        jQuery('#hideshow2').on('click', function(event) {      
             jQuery('#punto1').hide();
             jQuery('#punto2').show();
             jQuery('#punto3').hide();
        });
    });

jQuery(document).ready(function(){
        jQuery('#hideshow3').on('click', function(event) {      
             jQuery('#punto1').hide();
             jQuery('#punto2').hide();
             jQuery('#punto3').show();
        });
    });

Upvotes: 0

user2780362
user2780362

Reputation: 67

Show and hide are not needed when using .toggle(), .toggle() does a toggle on the state. Use .hide() and .show() to hide and show the divs.

Upvotes: 1

Related Questions