How to expand and collapse three div's side by side?

All we need is an easy explanation of the problem, so here it is.

$(document).ready(function () {
    $("#toggle").click(function () {
        if ($(this).data('name') == 'show') {
            $("#sidebar").animate({
                width: '10%'
            }).hide()
            $("#map").animate({
                width: '89%'
            });
            $(this).data('name', 'hide')
        } else {
            $("#sidebar").animate({
                width: '29%'
            }).show()
            $("#map").animate({
                width: '70%'
            });
            $(this).data('name', 'show')
        }
    });
});
html, body {
    width:100%;
    height: 100%;
}
#header {
    width: 100%;
    height: 20%;
    float: left;
    border: 1px solid;
}
#map {
    width: 80%;
    height: 80%;
    float: left;
    border: 1px solid;
}
#sidebar {
    width: 19%;
    height: 80%;
    float: left;
    border: 1px solid;
}
#toggle {
    width: 10%;
    height: 40%;
    margin-right: 6.5%;
    margin-top: 3.5%;
    float: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="header">HEADER
    <input type="button" data-name="show" value="Toggle" id="toggle">
</div>
<div id="map">MAP</div>
<div id="sidebar">SIDEBAR</div>

I am a beginner in angularjs, jquery and css. I want to create three div with toggle side by side
Please help me how to do that in angularjs.

In normal mode Example:-

enter image description here

It will be like this.

If I expand center div it needs to be like this Example:-

enter image description here

If I expand last div it needs to be like this Example:-

enter image description here

Thanks..

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Try this. All the div can be expanded in any order. To switch back into normal position, click on the expanded div again.

Width in compressed and expanded states are expressed in percentage and you can change them in the css, according to your requirement. Also I added transition property for smooth functioning.

Here’s a pen.

$("a.expansion-btn").click(function (){
  classes = this.className;
  var divNumber = classes.slice(-1);
  var toGetId = "#div-"+divNumber;
  if ($(toGetId).hasClass("expanded-div")){
   $(".normal-div").removeClass("compressed-div expanded-div");
  }
  else{
   $(".normal-div").removeClass("compressed-div expanded-div").addClass("compressed-div");;
   $(toGetId).removeClass("compressed-div").addClass("expanded-div");    
  }  
});
*{
  box-sizing:border-box;
}
.container{
  margin:0;
  padding:0;
  width:100%;
  height:400px;
}
.normal-div{
  width:33.33%;
  height:100%;
  position:relative;
  border:2px solid black;
  float:left;
  -webkit-transition: all 0.5s ease-in-out;
  -moz-transition: all 0.5s ease-in-out;
  transition: all 0.5s ease-in-out;
}
.expanded-div{
  width:80%;
}
.compressed-div{
  width:10%;
}
#div-1{
  background-color:green;
}
#div-2{
  background-color:red;
}
#div-3{
  background-color:blue;
}
a.expansion-btn{
  position:absolute;
  top:10px;
  right:10px;
  font-weight:bold;
  cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="normal-div" id="div-1">
    <a class="expansion-btn exp-1">click</a>
  </div>
  <div class="normal-div" id="div-2">
    <a class="expansion-btn exp-2">click</a>
  </div>
  <div class="normal-div" id="div-3">
    <a class="expansion-btn exp-3">click</a>
  </div>
</div>

Method 2

If you just want to toggle between divs then do something like this.

// varible for holding div index
var i = 0,
  // cache divs
  $div = $('.div');;

// bind click event handler
$('.toggle').click(function() {
  $div
  // remove both class from all elements
    .removeClass('active nonactive')
    // get element by index
    .eq(i)
    // add active class
    .addClass('active')
    // get siblings
    .siblings()
    // add nonactive class
    .addClass('nonactive');
  // update index 
  i = ++i % $div.length;
})
.div {
  height: 300px;
  width: 30%;
  border: solid 1px black;
  display: inline-block
}
.active {
  width: 75%;
}
.nonactive {
  width: 10%;
}
.active,
.nonactive {
  -webkit-transition: width 1s ease-in-out;
  -moz-transition: width 1s ease-in-out;
  -o-transition: width 1s ease-in-out;
  transition: width 1s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="toggle">toggle</button>
<br>
<div class="div"></div>
<div class="div"></div>
<div class="div"></div>

Or if you want to toggle when clicked a button inside the div then do something like this.

$('.toggle').click(function() {
  $(this)
    // get div 
    .parent()
    // remove nonactive class from clicked element
    .removeClass('nonactive')
    // toggle active class
    .toggleClass('active')
    // get sibling divs
    .siblings()
    // remove active class from siblings
    .removeClass('active')
    // toggle nonactive class based on the clicked element 
    .toggleClass('nonactive', $(this).parent().is('.active'));
})
.div {
  height: 300px;
  width: 30%;
  border: solid 1px black;
  display: inline-block
}
.active {
  width: 75%;
}
.nonactive {
  width: 10%;
}
.div,
.active,
.nonactive {
  -webkit-transition: width 1s ease-in-out;
  -moz-transition: width 1s ease-in-out;
  -o-transition: width 1s ease-in-out;
  transition: width 1s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <div class="div">
    <button class="toggle">toggle</button>
  </div>
  <div class="div">
    <button class="toggle">toggle</button>
  </div>
  <div class="div">
    <button class="toggle">toggle</button>
  </div>
</div>

Method 3

    <div id="header">HEADER
        <input type="button" data-name="show" value="Toggle" id="toggle">
    </div>
    <div id="maincont">
        <div id="map" class="active">MAP</div>
        <div id="sidebar" class="inactive">SIDEBAR</div>
        <div id="sidebar1" class="inactive">SIDEBAR1</div>
    </div>

script:

    $(document).ready(function () {     
            $("#toggle").click(function () {

                        var $div = $('#maincont').find(".active");
                        $div.removeClass('active').addClass("inactive").next().addClass("active");      

                        $('#maincont').find(".inactive").animate({
                            width: '10%'
                        })

                        $('#maincont').find(".active").animate({
                            width: '79%'
                        });           

             });

    });

css.

         html, body {
            width:100%;
            height: 100%;
        }
        #header {
            width: 100%;
            height: 100px;
            float: left;
            border: 1px solid;
        }
        #map {  
            height: 80%;
            float: left;
            border: 1px solid;
        }
        .active{
          width:78%;
           float: left;
           height: 100px;
        }
        .inactive{
          width:10%;
           float: left;
           border: 1px solid;
            height: 100px;
        }
        #sidebar {   
            height: 80%;
            float: left;

        }
        #toggle {
            width: 10%;
            height: 40%;
            margin-right: 6.5%;
            margin-top: 3.5%;
            float: right;
        }

fiddle link

Method 4

Since you tagged your question with angularjs, here is a simple solution with no fancy CSS:

Suppose you have some array of objects that describe the panels/divs in the controller, e.g.

$scope.panels = [{
    title: "One",
    expanded: true
  }, {
    title: "Two"
  }, {
    title: "Three"
  }];

The expanded flag just track which panel is actually expanded. By default the first one.

Then when you click on a panel, this function set the flag to the selected panel:

  $scope.expandPanel = function(panel) {
     $scope.panels.forEach(p => p.expanded = false);
     panel.expanded = true;
  }

And you display all that in a ng-repeat loop where the key thing is to set dynamically the class depending on the expanded flag with ng-class:

<div class="panel" 
     ng-class="{'expanded': panel.expanded, 'reduced': !panel.expanded}" 
     ng-repeat="panel in panels" ng-click="expandPanel(panel)">
  <span>{{panel.title}}</span>
</div> 

See it live with this plunker.

Note: .panel, .expanded and .reduced classes are define in the plunker css file.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply