Dynamic HTML5 Drawer

3

Good morning! I've built several blocks with a div that through JavaScript, it interacts as if you were opening a drawer (block) with a click and closing it with two clicks through a function.

  

However, when you open one block and the other at the same time, the two open on the same page, taking the visual style of the HTML / CSS structure. And when all of them open at the same time, there is a disorganized structure, because I have defined that the 5 blocks (guides) occupy a width of 4% and the "drawer" that would be opened, had the width of 80%. This error happens because the maximum width of the page goes up to 100% and all open windows, exceeds the defined width, leaving all the blocks one underneath the other.

function Exibir1() {
  document.getElementById("div01").style.display = "block";
}
function Ocultar1(){
  document.getElementById("div01").style.display = "none";
}
function Exibir2() {
  document.getElementById("div02").style.display = "block";
}
function Ocultar2(){
  document.getElementById("div02").style.display = "none";
}
function Exibir3() {
  document.getElementById("div03").style.display = "block";
}
function Ocultar3(){
  document.getElementById("div03").style.display = "none";
}
function Exibir4() {
  document.getElementById("div04").style.display = "block";
}
function Ocultar4(){
  document.getElementById("div04").style.display = "none";
}
function Exibir5() {
  document.getElementById("div05").style.display = "block";
}
function Ocultar5(){
  document.getElementById("div05").style.display = "none";
}
#blockpop{
  background-color: lightgray;
  width: 4%;
  height: 300px;
  float: left;
  border: 1px solid;
  padding-top: 9%;
  padding-left: 1.9%;
}
h2{
  width: 50%;
}
#textblock{
  transform: rotate(-90deg);
  width: 700%;
  margin-left: -350%;
  text-align: center;
  font-size: 10px;
  font-weight: bold;
}
#div01{background-color: red;}
#div02{background-color: gold;}
#div03{background-color: lightgreen;}
#div04{background-color: royalblue;}
#div05{background-color: pink;}
#div01,#div02,#div03,#div04,#div05{
  width: 80%;
  float: left;
  display: none;
  padding-left: 1%;
  height: 300px;
  overflow-x: auto;
}
   <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
  <div id="blockpop" onclick="Exibir1()" ondblclick="Ocultar1()">
        <div id="textblock">BLOCO 1</div>
    </div>
    <div id="div01">
        <h2>BLOCO 1</h2>
        <b>conteúdo</b><br>
    </div>
    <div id="blockpop" onclick="Exibir2()" ondblclick="Ocultar2()">
        <div id="textblock">BLOCO 2</div>
    </div>
    <div id="div02">
        <h2>BLOCO 2</h2>
        <b>conteúdo</b>
    </div>
    <div id="blockpop" onclick="Exibir3()" ondblclick="Ocultar3()">
        <div id="textblock">BLOCO 3</div>
    </div>
    <div id="div03">
        <h2>BLOCO 3</h2>
        <b>conteúdo</b>
    </div>
    <div id="blockpop" onclick="Exibir4()" ondblclick="Ocultar4()">
        <div id="textblock">BLOCO 4</div>
    </div>
    <div id="div04">
        <h2>BLOCO 4</h2>
        <b>conteúdo</b>
    </div>
    <div id="blockpop" onclick="Exibir5()" ondblclick="Ocultar5()">
        <div id="textblock">BLOCO 5</div>
    </div>
    <div id="div05">
        <h2>BLOCO 5</h2>
        <b>conteúdo</b>
    </div>
  

In this way, what would be the most practical way to create a script that when you open a block, close all others that are open on the page? Is it possible to create a function within the onclick attribute in a tag that recognizes only two clicks to open and close any block?

    
asked by anonymous 31.12.2018 / 10:10

2 answers

2

I am putting this answer only as complementary help requested by the question author in the question comments.

Option 1

With label + input type radio

OnlywithCSSyoucanuseaCSSruleandreplacedivblockpopwithalabel,andusethatlabeltoactivatearadio.buttonthatdependsonthe:checkedestatewillshowacontentandhidethecontentsothers.

NOTE:Thedisadvantageofthismodelisthatonceyouclickedonsomebtnyoucannotcloseit,itonlyclosesifyouopenanotherbtn...

.blockpop{
  background-color: lightgray;
  width: 4%;
  height: 300px;
  float: left;
  border: 1px solid;
  padding-top: 9%;
  padding-left: 1.9%;
  box-sizing: border-box;
}
h2{
  width: 50%;
}
.textblock{
  transform: rotate(-90deg);
  width: 700%;
  margin-left: -350%;
  text-align: center;
  font-size: 10px;
  font-weight: bold;
}
.div01{background-color: red;}
.div02{background-color: gold;}
.div03{background-color: lightgreen;}
.div04{background-color: royalblue;}
.div05{background-color: pink;}
.div01,.div02,.div03,.div04,.div05{
  width: 0%;
  float: left;
  /* display: none; */
  padding-left: 0%;
  height: 300px;
  overflow-x: auto;
  box-sizing: border-box;
  transition: all 1s linear;
}
[type="radio"]:checked + div,
[type="radio"]:checked + div,
[type="radio"]:checked + div,
[type="radio"]:checked + div,
[type="radio"]:checked + div{
  width: 80%;
  padding-left: 1%;
}
[type="radio"] {
  display: none;
}
<label for="btn1" class="blockpop" >
  <div class="textblock">BLOCO 1</div>
</label>
<input type="radio" name="btns" id="btn1">
<div class="div01">
  <h2>BLOCO 1</h2>
  <b>conteúdo</b><br>
</div>
<label for="btn2" class="blockpop" >
  <div class="textblock">BLOCO 2</div>
</label>
<input type="radio" name="btns" id="btn2">
<div class="div02">
  <h2>BLOCO 2</h2>
  <b>conteúdo</b>
</div>
<label for="btn3" class="blockpop" >
  <div class="textblock">BLOCO 3</div>
</label>
<input type="radio" name="btns" id="btn3">
<div class="div03">
  <h2>BLOCO 3</h2>
  <b>conteúdo</b>
</div>
<label for="btn4" class="blockpop" >
  <div class="textblock">BLOCO 4</div>
</label>
<input type="radio" name="btns" id="btn4">
<div class="div04">
  <h2>BLOCO 4</h2>
  <b>conteúdo</b>
</div>
<label for="btn5" class="blockpop" >
  <div class="textblock">BLOCO 5</div>
</label>
<input type="radio" name="btns" id="btn5">
<div class="div05">
  <h2>BLOCO 5</h2>
  <b>conteúdo</b>
</div>

Option 2

With jQuery

You can use a .ativo class by making a toggleClass to determine the item that was clicked and open it at the same time as using the .siblings () method you remove the siblings class.

Seethecodefortheimageabove:

$(".blockpop").click(function(event){
   $(this).toggleClass("ativo").siblings().removeClass("ativo");
});
.blockpop{
  background-color: lightgray;
  width: 4%;
  height: 300px;
  float: left;
  border: 1px solid;
  padding-top: 9%;
  padding-left: 1.9%;
  box-sizing: border-box;
}
h2{
  width: 50%;
}
.textblock{
  transform: rotate(-90deg);
  width: 700%;
  margin-left: -350%;
  text-align: center;
  font-size: 10px;
  font-weight: bold;
}
.div01{background-color: red;}
.div02{background-color: gold;}
.div03{background-color: lightgreen;}
.div04{background-color: royalblue;}
.div05{background-color: pink;}

.div01,
.div02,
.div03,
.div04,
.div05{
  width: 0%;
  float: left;
  padding-left: 0%;
  height: 300px;
  overflow-x: auto;
  box-sizing: border-box;
  transition: all 1s linear;
}
.blockpop.ativo + div{
  width: 80%;
  padding-left: 1%;
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script><divclass="blockpop" >
  <div class="textblock">BLOCO 1</div>
</div>
<div class="div01">
  <h2>BLOCO 1</h2>
  <b>conteúdo</b><br>
</div>
<div class="blockpop" >
  <div class="textblock">BLOCO 2</div>
</div>
<div class="div02">
  <h2>BLOCO 2</h2>
  <b>conteúdo</b>
</div>
<div class="blockpop" >
  <div class="textblock">BLOCO 3</div>
</div>
<div class="div03">
  <h2>BLOCO 3</h2>
  <b>conteúdo</b>
</div>
<div class="blockpop" >
  <div class="textblock">BLOCO 4</div>
</div>
<div class="div04">
  <h2>BLOCO 4</h2>
  <b>conteúdo</b>
</div>
<div class="blockpop" >
  <div class="textblock">BLOCO 5</div>
</div>
<div class="div05">
  <h2>BLOCO 5</h2>
  <b>conteúdo</b>
</div>
    
31.12.2018 / 20:03
3

Instead of creating multiple functions for each id, you can use something more generic. First you need to rephrase your HTML, eliminating the repeated id's, changing them to class , and adjusting CSS accordingly.

Instead of using onclick and ondblclick , use event handlers , which will make your code cleaner and better because you can include your code in document.addEventListener("DOMContentLoaded", function(){ avoiding global variables.

It is also interesting to insert the user-select: none; property into the CSS so that the div is not selected in the double-click.

Here's how it would look (explanatory comments in the code):

document.addEventListener("DOMContentLoaded", function(){

   // seleciona todos os elementos com a classe .blockpop
   var els = document.querySelectorAll(".blockpop");   
   for(var x=0; x<els.length; x++){
      
      // event handler do clique
      els[x].onclick = function(){

         // seleciona todos os blocos onde a "id" começa com "div"
         var blocos = document.querySelectorAll("div[id^=div]");
         
         // esconde todos os blocos
         for(var y=0; y<blocos.length; y++) blocos[y].style.display = "none";
         
         // mostra o elemento seguinte ao bloco clicado
         this.nextElementSibling.style.display = "block";

      }

      // event handler do clique duplo
      els[x].ondblclick = function(){
         // esconde o elemento seguinte ao bloco clicado
         this.nextElementSibling.style.display = "none";
      }
   }
   
});
.blockpop{
  background-color: lightgray;
  width: 4%;
  height: 300px;
  float: left;
  border: 1px solid;
  padding-top: 9%;
  padding-left: 1.9%;

   /* evita a selecionar no clique duplo */
   -webkit-user-select: none;
   -moz-user-select: none;
   -khtml-user-select: none;
   -ms-user-select: none;
   user-select: none;
}
h2{
  width: 50%;
}
.textblock{
  transform: rotate(-90deg);
  width: 700%;
  margin-left: -350%;
  text-align: center;
  font-size: 10px;
  font-weight: bold;
}
#div01{background-color: red;}
#div02{background-color: gold;}
#div03{background-color: lightgreen;}
#div04{background-color: royalblue;}
#div05{background-color: pink;}
#div01,#div02,#div03,#div04,#div05{
  width: 80%;
  float: left;
  display: none;
  padding-left: 1%;
  height: 300px;
  overflow-x: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><linkrel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script><divclass="blockpop">
   <div class="textblock">BLOCO 1</div>
</div>
<div id="div01">
   <h2>BLOCO 1</h2>
   <b>conteúdo</b><br>
</div>
<div class="blockpop">
   <div class="textblock">BLOCO 2</div>
</div>
<div id="div02">
   <h2>BLOCO 2</h2>
   <b>conteúdo</b>
</div>
<div class="blockpop">
   <div class="textblock">BLOCO 3</div>
</div>
<div id="div03">
   <h2>BLOCO 3</h2>
   <b>conteúdo</b>
</div>
<div class="blockpop">
   <div class="textblock">BLOCO 4</div>
</div>
<div id="div04">
   <h2>BLOCO 4</h2>
   <b>conteúdo</b>
</div>
<div class="blockpop">
   <div class="textblock">BLOCO 5</div>
</div>
<div id="div05">
   <h2>BLOCO 5</h2>
   <b>conteúdo</b>
</div>

With jQuery

If you want to use jQuery, just replace JavaScript with this one:

$(function(){

   $(".blockpop").on("click dblclick", function(e){

      if(e.type == "click"){
         $("div[id^=div]").hide();
         $(this).next().show();
      }else{
         $(this).next().hide();
      }

   });

});

With jQuery animation

If you want to animate, adjust the CSS by putting the divs with width: 0 and padding-left: 0 and remove display: none :

$(function(){

   $(".blockpop").on("click dblclick", function(e){
      
      $this = $(this);
      $next = $this.next();
      
      if(e.type == "click"){
      
         $("div[id^=div]").not($next).css({
            width: 0,
            paddingLeft: 0
         });

         if($next.width() == 0){
            $next.animate({
               width: "80%",
               paddingLeft: "1%"
            });
         }

      }else{

         $next.animate({
            width: 0,
            paddingLeft: 0
         });

      }

   });

});
.blockpop{
  background-color: lightgray;
  width: 4%;
  height: 300px;
  float: left;
  border: 1px solid;
  padding-top: 9%;
  padding-left: 1.9%;

   /* evita a selecionar no clique duplo */
   -webkit-user-select: none;
   -moz-user-select: none;
   -khtml-user-select: none;
   -ms-user-select: none;
   user-select: none;
}
h2{
  width: 50%;
}
.textblock{
  transform: rotate(-90deg);
  width: 700%;
  margin-left: -350%;
  text-align: center;
  font-size: 10px;
  font-weight: bold;
}
#div01{background-color: red;}
#div02{background-color: gold;}
#div03{background-color: lightgreen;}
#div04{background-color: royalblue;}
#div05{background-color: pink;}
#div01,#div02,#div03,#div04,#div05{
  width: 0;
  float: left;
  padding-left: 0;
  height: 300px;
  overflow-x: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><linkrel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script><divclass="blockpop">
   <div class="textblock">BLOCO 1</div>
</div>
<div id="div01">
   <h2>BLOCO 1</h2>
   <b>conteúdo</b><br>
</div>
<div class="blockpop">
   <div class="textblock">BLOCO 2</div>
</div>
<div id="div02">
   <h2>BLOCO 2</h2>
   <b>conteúdo</b>
</div>
<div class="blockpop">
   <div class="textblock">BLOCO 3</div>
</div>
<div id="div03">
   <h2>BLOCO 3</h2>
   <b>conteúdo</b>
</div>
<div class="blockpop">
   <div class="textblock">BLOCO 4</div>
</div>
<div id="div04">
   <h2>BLOCO 4</h2>
   <b>conteúdo</b>
</div>
<div class="blockpop">
   <div class="textblock">BLOCO 5</div>
</div>
<div id="div05">
   <h2>BLOCO 5</h2>
   <b>conteúdo</b>
</div>
    
31.12.2018 / 15:06