HTML5 Dynamic Drawer

Asked

Viewed 226 times

3

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

But when you open one block and the other at the same time, the two are open on the same page, taking the visual style out of the HTML/CSS structure. And when you open them all at the same time, there is a disorganized structure, because I defined that the 5 blocks (guides) occupy a width of 4% and the "drawer" that was going to be opened, would be 80% wide. This error happens because the maximum width of the page goes up to 100% and all windows open, exceeds the defined width, leaving all the blocks under each 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 opening a block, close all others that are open on the page? It is possible to create a function within the attribute onclick in a tag that recognizes only two clicks to open and close any block?

  • I don’t know if it’s just because of studies and you really want to know how it does with JS, but this component is possible to do only with CSS, if you are interested I can make a template.

  • Yes, I would be grateful if you had a practical example here in the post, because I’ve seen this method done only with pre-defined functions in Javascript, already only by CSS, never heard of this form.

  • Dude I made the model and is 100% functional, the problem is that it is not exactly as you want, because it does not close at double click, actually after opened it is open, but alternates closing one when opening another normally... See this gif, if you are interested I put as a response option... https://imgur.com/a/w9EBkAZ

  • I managed to do it with jQuery opening and closing the way you want, only with a simple click to close and not with a double click to close. But the rest is 100%, open one and close the others, and if you click what is open it closes. One problem I noticed in your code is that you are repeating the ID on several elements, this is not cool, until pq a simple css class would be more suitable. If you want I can include in the answer the two codes https://imgur.com/a/3LsmG4z

  • @hugocsl, you can put yes, it is even good for some users to see and be interested in the subject, because there are some websites that have various information that choose to use this form of content division. But, if possible, you can put as an answer here in the post. ;-)

  • By the way, I used the ondblclick as if it were an improvisation, as I worked very little with these events in my course, so I tried to simulate a drawer with only two functions.

Show 1 more comment

2 answers

3

Instead of creating multiple functions for each id, you can use something more generic. First you need to reshape your HTML by deleting the repeated id’s, swapping them for class, and adjust the CSS accordingly.

Instead of using onclick and ondblclick, utilize Event handlers, that will make your code cleaner and better, as you can include your code in document.addEventListener("DOMContentLoaded", function(){ avoiding global variables.

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

See 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>
<link rel="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>

<div class="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:

$(function(){

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

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

   });

});

With animation jQuery

If you want to animate, adjust the CSS by placing the Divs with width: 0 and padding-left: 0 and remove the 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>
<link rel="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>

<div class="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>

2


I am putting this answer only as supplementary aid requested by the questioner in the comments of the question.

Option 1

With label + input type radio

inserir a descrição da imagem aqui

Only with CSS you can use a CSS rule and replace the div blockpop by a label, and use that label to activate a radio.button that depends on the state :checkede will show content and hide others.

OBS: The disadvantage of this model is that once you clicked on some btn vc can’t close it, it only closes if you open another btn...

.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 class .ativo making a toggleClass to determine the item that was clicked and open it at the same time using the . siblings() method you remove the siblings class.

inserir a descrição da imagem aqui

See the code for the image above:

$(".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>

<div class="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>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.