Reputation: 1204
This is hard to explain so bear with me.
I have a column on my webpage that is divided into 2 panels/sections. When the user minimizes a panel, I want the secondary panel to expand to take up the remaining space.
When Panel 1 is minimized, the list hides, panel 2 header will move up directly underneath panel 1 and the list will expand to fill the rest of the column space below.
When Panel 2 is minimized, the list inside hides, panel 2 header will go directly to the bottom of the page and panel 1 list will expand to fit the rest of the column
Fiddle: http://jsfiddle.net/mL9RG/
I can get the lists inside the sections to slideToggle no problem. I can also add a fixed CSS height animation to kind of achieve what I am looking for. I have not had success with %'s to make it responsive.
HTML
<div id="wrapper">
<div id="section1">
<h2 id="crossbar1">Section 1<span id="plus2">+/-</span></h2>
<ul id="list1">
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
</ul>
</div>
<div id="section2">
<h2 id="crossbar2">Section 2 <span id="plus2">+/-</span></h2>
<ul id="list2">
<li>Stuff</li>
<li>More Stuff</li>
<li>Stuff</li>
</ul>
</div>
</div>
CSS
#wrapper { width: 200px; height: 400px; margin: 0 auto; background-color: #eaeaea; }
ul { margin: 0; padding: 0; list-style: none; display: block; }
h2 { margin: 0; padding: 5px 0; background-color: #d8d8d8; position: relative; }
h2 span { position: absolute; right: 10px; font-size: 15px; top: 10px; cursor: pointer }
#section1 {
height: 50%; width: 100%; background-color: blue;
box-sizing: border-box;
}
#section2 {
height: 50%; width: 100%; background-color: green;
}
jquery
$('#crossbar1').click(function(){
$('#list1').slideToggle();
});
$('#crossbar2').click(function(){
$('#list2').slideToggle();
});
Upvotes: 1
Views: 2522
Reputation: 234
Take a look at my solution with animating the height. The behavior should be similar to your images.
Modified css:
#wrapper {
width: 200px; height: 400px; margin: 0 auto; background-color: #eaeaea;
position: relative;
}
ul { margin: 0; padding: 0; list-style: none; display: block; }
h2 { margin: 0; padding: 5px 0; background-color: #d8d8d8; position: relative; }
h2 span { position: absolute; right: 10px; font-size: 15px; top: 10px; cursor: pointer }
#section1, #section2{
box-sizing: border-box;
width: 100%;
height: 50%;
}
#section1 {
background-color: blue;
}
#section2 {
background-color: green;
}
Modified js
$('#crossbar1').click(function(){
if($('#list1').is(':hidden')){
if($('#list2').is(':hidden')){
$( "#section1" ).animate({height: "362px"});
$( "#section2" ).animate({height: "37px"});
}else{
$( "#section1" ).animate({height: "50%"});
$( "#section2" ).animate({height: "50%"});
}
}else{
if($('#list1').is(':hidden')){
$( "#section1" ).animate({height: "362px"});
}else{
$( "#section1" ).animate({height: "37px"});
$( "#section2" ).animate({height: "362px"});
}
}
$('#list1').slideToggle();
});
$('#crossbar2').click(function(){
if($('#list2').is(':hidden')){
if($('#list1').is(':hidden')){
$( "#section2" ).animate({height: "362px"});
}else{
$( "#section2" ).animate({height: "50%"});
$( "#section1" ).animate({height: "50%"});
}
}else{
if($('#list1').is(':hidden')){
$( "#section2" ).animate({height: "362px"});
}else{
$( "#section2" ).animate({height: "37px"});
$( "#section1" ).animate({height: "362px"});
}
}
$('#list2').slideToggle();
});
Check out the demo on jsFiddle. Hope that's what you'r looking for.
Edit: Small bugfix by closed section2 and opening and closing section1. (Updated jsFiddle-Demo)
Upvotes: 0
Reputation: 11496
HTML
<div class="wrapper">
<div class="wrapper-item">
Section 1
<div class="type"></div>
</div>
<div class="data">
<ul id="list1">
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
</ul>
</div>
<div class="wrapper-item">
Section 2
<div class="type"></div>
</div>
<div class="data">
<ul id="list1">
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
</ul>
</div>
CSS
body
{
font-family: Arial, Helvetica, sans-serif;
}
.wrapper
{
width:100%;
max-height:300px;
margin:20px auto;
}
.wrapper-item {
font-size: 1em;
margin: 0 10px 0 10px;
padding: 10px;
height: 20px;
background: #f2f2f2;
border-bottom:1px solid #ccc;
color: #000;
cursor:pointer;
}
.wrapper-item.open
{
background:#14ad40;
border-bottom:0px;
color:#fff;
}
.wrapper-item.open .type {
float: right;
background: url('http://vivekarora.com/images/minus.png') center no-repeat;
padding: 10px;
}
.wrapper-item .type {
float: right;
background: url('http://vivekarora.com/images/plus.png') center no-repeat;
padding: 10px;
}
div.data {
background: #fff;
margin: 0 10px 0 10px;
padding: 10px;
border:1px solid #ccc;
font-size: .8em;
line-height: 140%;
display:none;
}
JS
$(function($) {
var allWrappers = $('.wrapper div.data');
var allWrapperItems = $('.wrapper .wrapper-item');
$('.wrapper > .wrapper-item').click(function() {
if($(this).hasClass('open'))
{
$(this).removeClass('open');
$(this).next().slideUp("slow");
}
else
{
allWrappers.slideUp("slow");
allWrapperItems.removeClass('open');
$(this).addClass('open');
$(this).next().slideDown("slow");
return false;
}
});
});
Upvotes: 1
Reputation: 1497
universal solution Fiddle
HTML
<div class="wrapper">
<div class="section expanded">
<h2>Section 1<span class="toggle">+/-</span></h2>
<ul class="list">
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
</ul>
</div>
<div class="section expanded">
<h2>Section 2<span class="toggle">+/-</span></h2>
<ul class="list">
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
</ul>
</div>
<div class="section expanded">
<h2>Section 3<span class="toggle">+/-</span></h2>
<ul class="list">
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
</ul>
</div>
css
.wrapper {
width: 200px;
height: 400px;
margin: 0 auto;
background-color: #eaeaea;
position: relative;
}
ul {
margin: 0;
padding: 0;
list-style: none;
display: block;
}
h2 {
margin: 0;
padding: 0;
height:38px;
line-height:38px;
background-color: #d8d8d8;
position: relative;
}
h2 span {
position: absolute;
right: 10px;
font-size: 15px;
top: 0px;
cursor: pointer
}
.section {
position: relative;
overflow:hidden;
}
script
function recalc(){
var jq_parent = $(this).closest('.section');
jq_parent.attr('class', 'section ' + (jq_parent.hasClass('expanded') ?
'collapsed' : 'expanded'));
var num = $('.expanded').length;
if (num > 0) {
var h = (400 - (38 * $('.collapsed').length) )/ num;
$('.collapsed').animate({height:'38px'});
$('.expanded').animate({height: h + 'px' });
}
}
$('.toggle').click(recalc);
recalc();
Upvotes: 2
Reputation: 21170
What I suggest is you use jQuery's .toggleClass()
function.
If you make two additional classes:
.open {
height: 50%;
}
.fullOpen {
height: 100%;
}
You can then control the states of the content boxes as follows:
$('#crossbar1').click(function(){
$("#one").toggleClass('open', 100);
$('#bodyOne').slideToggle(100);
$("#two").toggleClass('fullOpen', 100);
});
$('#crossbar2').click(function(){
$("#two").toggleClass('open', 100);
$('#bodyTwo').slideToggle(100);
$("#one").toggleClass('fullOpen', 100);
});
This works perfectly and does exactly as you implied.
You can also achieve it by explicitly keeping track of the states of the boxes:
Hope this helps you out!
Upvotes: 0
Reputation: 105885
I assume that you used the div#section
in order to create the effect, and that you don't need them, which gives us cleaner markup and less nodes in the DOM:
<div id="wrapper">
<h2 id="crossbar1">Section 1<span id="plus1">+/-</span></h2>
<ul id="list1">
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
</ul>
<h2 id="crossbar2">Section 2 <span id="plus2">+/-</span></h2>
<ul id="list2">
<li>Stuff</li>
<li>More Stuff</li>
<li>Stuff</li>
</ul>
</div>
Now we set #wrapper
to be a flexbox (via display: flex
), and say that we want to use it in a column fashion (flex-direction: column
), that means, that the content will spread out vertically. Also, we set the flex-grow
on the lists to 1
, so that they will grow if necessary:
#wrapper { display: flex; flex-flow: column nowrap;
width: 200px; height: 400px; margin: 0 auto; background-color: #eaeaea; }
#wrapper > ul { flex-grow:1; margin: 0; padding: 0; list-style: none; }
/* your old rules */
h2 { margin: 0; padding: 5px 0; background-color: #d8d8d8; position: relative; }
h2 span { position: absolute; right: 10px; font-size: 15px; top: 10px; cursor: pointer }
#list1{background-color: blue}
#list2{background-color: green}
For the mutual behaviour, I've chosen an approach which is easy to extend to more sections:
var addToToggleGroup = (function(){
var toggleState = []; // holds the state of the elements in the group
var toggle = function(i, target) {
toggleState[i] = !toggleState[i];
// prevent that we toggle this element if it is the last
if(toggleState.every(function(el){ return !el;})){
toggleState[i] = !toggleState[i];
return;
} else {
$(target).slideToggle();
}
}
return function (el, target){
var i = toggleState.length;
toggleState.push(true);
$(el).on("click", function(){
toggle(i, target);
})
}
})();
// add the elements to the toggle group. We can use jQuery selectors here
addToToggleGroup("#crossbar1","#list1");
addToToggleGroup("#crossbar2","#list2");
And that's it (fiddle).
Upvotes: 0
Reputation: 695
It sounds like you are describing the behavior implemented by Bootstrap's collapse plugin, is that correct? See an example here: http://getbootstrap.com/javascript/#collapse
Upvotes: 0
Reputation: 2853
Try this approach to achieve what you want.
I have used class instead of id. it will make code very short.
HTML
<div id="wrapper">
<div class="section">
<h2 class="crossbar">Section 1<span id="plus2">+/-</span></h2>
<ul id="list1">
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
<li>Stuff</li>
</ul>
</div>
<div class="section">
<h2 class="crossbar">Section 2 <span id="plus2">+/-</span></h2>
<ul id="list2">
<li>Stuff</li>
<li>More Stuff</li>
<li>Stuff</li>
</ul>
</div>
</div>
CSS
#wrapper { width: 200px; height: 400px; margin: 0 auto; background-color: #eaeaea; }
ul { margin: 0; padding: 0; list-style: none; display: block; }
h2 { margin: 0; padding: 5px 0; background-color: #d8d8d8; position: relative; }
h2 span { position: absolute; right: 10px; font-size: 15px; top: 10px; cursor: pointer }
.section{
width: 100%;
box-sizing: border-box;
}
#list1{ height: 150px; background-color: blue;}
#list2{ height: 150px; background-color: green;}
Script
$('h2.crossbar').on('click', function(){
$(this).next('ul').slideToggle();
});
Upvotes: 0