Dynamically changing columns sizes on click - javascript

I would like to have three columns on my page, but column2 should initially have a size of column size of 0, ie col-md-0. When the user clicks on a link in the navigation bar, I would like column2 to expand to col-md-3, and column3 should shrink to adjust.
For example, this is what I would imagine my columns' html to be when the page is loaded:
<div class="container-fluid">
<div class="row no-gutter">
<div id="col1" class="col-md-1">
<vs-navbar></vs-navbar>
</div>
<div id="col2" class="col-md-0">
<router-outlet></router-outlet>
</div>
<div id="col3" class="col-md-11">
<div class="placeholder">
</div>
</div>
</div>
</div>
The navbar could be:
<nav class="navbar navbar-inverse navbar-full">
<ul class="nav nav-stacked">
<li>
<a>Home</a>
</li>
<li>
<a>Info</a>
</li>
</ul>
</nav>
When the Info link is clicked, I would like the html to transition to:
<div class="container-fluid">
<div class="row no-gutter">
<div id="col1" class="col-md-1">
<vs-navbar></vs-navbar>
</div>
<div id="col2" class="col-md-3">
<router-outlet></router-outlet>
</div>
<div id="col3" class="col-md-8">
<div class="placeholder">
</div>
</div>
</div>
</div>
I have a vague but messy idea how this could be done with some javascript, but I've seen this kind of thing on several sites so I'm looking for the clean, recommended way of doing this, especially as I'm using bootstrap.

Because you have IDs, I assume you now the exact structure of your row.
If it is so, a solution can be based on toggleClass:
$('a:contains("Info")').on('click', function(e) {
$('#col2').toggleClass('col-md-0 col-md-3')
$('#col3').toggleClass('col-md-11 col-md-8')
})
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<nav class="navbar navbar-inverse navbar-full">
<ul class="nav nav-stacked">
<li>
<a>Home</a>
</li>
<li>
<a>Info</a>
</li>
</ul>
</nav>
<div class="container-fluid">
<div class="row no-gutter">
<div id="col1" class="col-md-1">
<vs-navbar>aaaaaa</vs-navbar>
</div>
<div id="col2" class="col-md-0">
<router-outlet>bbbbbb</router-outlet>
</div>
<div id="col3" class="col-md-11">
<div class="placeholder">cccc
</div>
</div>
</div>
</div>

You can use the :target pseudo-class for this.
The :target pseudo-class is used to style an element that is the
target of an internal link in a document.
Basically you hide your column, then when the user clicks the link it will show up:
#col2{
display: none;
}
#col2:target{
display: block;
}
CODE SNIPPET:
.row {
display: flex;
}
.col {
background-color: dodgerblue;
flex: 0 0 30%;
height: 100px;
}
.col:nth-child(odd) {
background-color: gold;
}
#col2 {
display: none;
animation: open 300ms linear both;
}
#col2:target {
display: block;
}
#keyframes open {
0 {
transform: rotateX(0);
}
55% {
transform: rotateX(90deg);
}
100% {
transform: rotateX(180deg);
}
}
Trigger Col 2
<div class="row">
<div id="col1" class="col"></div>
<div id="col2" class="col"></div>
<div id="col3" class="col"></div>
</div>
EDIT:
To change between .col-md-8 and .col-md-11, you can change the width of .col-md-8when your second column is not present, using the corresponding media query for md viewport.
#media (min-width: 992px) {
#col2 + .col-md-8 {
width: 91.66666667%;
}
#col2:target + .col-md-8 {
width: 66.66666667%;
}
}
Bootstrap demo:
div[class*="col"],
div[class^="col"] {
height: 100px;
}
#col1 {
background-color: gold;
}
#col3 {
background-color: purple;
}
#col2 {
background-color: dodgerblue;
display: none;
animation: open 300ms linear both;
}
#col2:target {
display: block;
}
#media (min-width: 992px) {
#col2 + .col-md-8 {
width: 91.66666667%;
}
#col2:target + .col-md-8 {
width: 66.66666667%;
}
}
#keyframes open {
0 {
transform: rotateX(0);
}
55% {
transform: rotateX(90deg);
}
100% {
transform: rotateX(180deg);
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
Trigger Col 2
<div class="container-fluid">
<div class="row no-gutter">
<div id="col1" class="col-md-1">
<vs-navbar></vs-navbar>
</div>
<div id="col2" class="col-md-3">
<router-outlet></router-outlet>
</div>
<div id="col3" class="col-md-8">
<div class="placeholder">
</div>
</div>
</div>
</div>

Related

How to add dropdown menu to another dropdown?

I want to create a class for adding dropdown to menu even in the other dropdowns. I almost did it, but there is a problem and when I try to close the inner drop-down, the outer drop-down also closes.
When you click on secondary dropdown the first one will also close. What should I do to fix this?
$(".dropdown").each(function() {
$(this).on("click", function() {
if ($(this).attr("data-dropdown") == "closed") {
$(this).attr("data-dropdown", "opened");
$(this).css({
"height": "auto"
});
} else {
$(this).attr("data-dropdown", "closed");
$(this).css({
"height": "35px"
});
}
})
})
#font-face {
font-family: iransans;
src: url(font/IRANSansWeb.ttf);
}
* {
padding: 0;
margin: 0;
font-family: iransans;
}
html,
body {
height: 100%;
}
.menu {
position: absolute;
left: 0;
top: 0;
bottom: 0;
background-color: burlywood;
width: 200px;
}
.dropdown,
.dropdown-child {
height: 35px;
overflow: hidden;
}
.dropdown-item {
display: block;
padding: 6px;
}
.menu .dropdown-item:hover {
background-color: blueviolet;
cursor: pointer;
color: white;
}
<script src="https://kit.fontawesome.com/91f5230546.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div class="menu">
<div class="menu-item">
<div class="dropdown col-lg-12 col-md-12 col-sm-12 col-12" data-dropdown="closed">
<span class="dropdown-item"> Category <span><i class="fas fa-angle-down"></i></span></span>
<div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div class="dropdown col-lg-12 col-md-12 col-sm-12 col-12" data-dropdown="closed">
<span class="dropdown-item"> Category <span><i class="fas fa-angle-down"></i></span></span>
<div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div>
<span class="dropdown-item">Category</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="menu-item">
<span>Category</span>
</div>
</div>
The main issue is because the event is propagating up the DOM, so although you click to toggle the child dropdown, the event is caught by the parent which then toggles and hides. To fix this problem, amend your click handler function to receive the event as an argument, then call stopPropagation() on it.
Also, note that you don't need to use each() here as jQuery will loop over all elements in the collection and assign the event to them. In addition you can simplify the code massively, just by using toggleClass().
Finally, it would be much better practice to hide/show the child div of the toggled dropdown instead of changing its height. This method allows you to perform more varied animations to transition the content from hidden to visible, and also prevents issues with text being clipped due to changes in font sizes or zoom levels.
Here's a working version:
$(".dropdown").on("click", e => {
e.stopPropagation();
$(e.currentTarget).toggleClass('open');
})
#font-face {
font-family: iransans;
src: url(font/IRANSansWeb.ttf);
}
* {
padding: 0;
margin: 0;
font-family: iransans;
}
html,
body {
height: 100%;
}
.menu {
position: absolute;
left: 0;
top: 0;
bottom: 0;
background-color: burlywood;
width: 200px;
}
.dropdown,
.dropdown-child {
overflow: hidden;
}
.dropdown>div {
display: none;
}
.dropdown.open>div {
display: block;
}
.dropdown-item {
display: block;
padding: 6px;
}
.menu .dropdown-item:hover {
background-color: blueviolet;
cursor: pointer;
color: white;
}
<script src="https://kit.fontawesome.com/91f5230546.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div class="menu">
<div class="menu-item">
<div class="dropdown col-lg-12 col-md-12 col-sm-12 col-12" data-dropdown="closed">
<span class="dropdown-item"> Category <span><i class="fas fa-angle-down"></i></span></span>
<div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div class="dropdown col-lg-12 col-md-12 col-sm-12 col-12" data-dropdown="closed">
<span class="dropdown-item"> Category <span><i class="fas fa-angle-down"></i></span></span>
<div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div>
<span class="dropdown-item">Category</span>
</div>
<div>
<span class="dropdown-item">Category</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="menu-item">
<span>Category</span>
</div>
</div>

Bootstrap Flex - Prevent Child Items from Stretching Container

I'm trying to establish a layout where everything can be viewed without scrolling. Any panels that needs more space should be scrollable. In the example below, instead of main-left being stretched, I would like it so that the contents of main-left is srollable and not stretch the entire row.
for (let i = 0; i < 20; i++) {
$("#main-left").append("<div>" + i + "</div>");
}
html,
body {
height: 100%;
max-height: 100vh;
}
#main {
background-color: cyan;
min-height: 100vh;
}
#main-right {
background-color: red;
}
#main-left {
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid d-flex flex-column" id="main">
<nav class="navbar">
<div class="container-fluid">
<div class="navbar-header">
<d class="navbar-brand">Header</d>
</div>
</div>
</nav>
<div class="row d-flex flex-grow-1 " id="main-row">
<div class="col-5 d-flex flex-column" id="main-left">
</div>
<div class="col-2" id="main-center">
</div>
<div class="col-5" id="main-right">
</div>
</div>
</div>
In order for an element to scroll, it must:
Have an explicit height
Have enough content to overflow that explicit height
Have overflow: auto or scroll declared
The following CSS rule will target all direct children of your #main-row and prevent them from stretching your container, allowing scroll:
#main-row > * {
max-height: 100%;
overflow: auto;
}
for (let i = 0; i < 30; i++) {
$("#main-left").append("<div>" + i + "</div>");
}
#main {
background-color: cyan;
max-height: 100vh;
overflow: hidden;
}
#main-row>* {
max-height: 100vh;
overflow: auto;
}
#main-right {
background-color: red;
}
#main-left {
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<div class="container-fluid d-flex flex-column" id="main">
<nav class="navbar">
<div class="container-fluid">
<div class="navbar-header">
<d class="navbar-brand">Header</d>
</div>
</div>
</nav>
<div class="row d-flex flex-grow-1 " id="main-row">
<div class="col-5 d-flex flex-column" id="main-left">
left
</div>
<div class="col-2" id="main-center">
center
</div>
<div class="col-5" id="main-right">
right
</div>
</div>
</div>

Make progress bars responsive

I have these progress bars which are suppose to work as ratings and they look good:
I have applied some CSS and I change their width with JavaScript by reading values from text files.
But are not responsive at all and whenever the window is resized:
HTML:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="second-part">
<div class="row">
<div class="side">
<div>5 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar11" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p11">150</div>
</div>
<div class="side">
<div>4 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar12" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p12">63</div>
</div>
<div class="side">
<div>3 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar13" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p13">15</div>
</div>
<div class="side">
<div>2 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar14" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p14">6</div>
</div>
<div class="side">
<div>1 star</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar15" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p15">20</div>
</div>
</div>
</div>
CSS:
* {
box-sizing: border-box;
}
/* Three column layout */
.side {
float: left;
width: 15%;
margin-top:10px;
}
.middle {
margin-top:10px;
float: left;
width: 70%;
}
/* Place text to the right */
.right {
text-align: left;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* The bar container */
.bar-container {
width: 90%;
background-color: #f1f1f1;
text-align: center;
color: white;
}
/* Responsive layout - make the columns stack on top of each other instead of next to each other */
#media (max-width: 400px) {
.side, .middle {
width: 100%;
}
.right {
display: none;
}
}
JavaScript to change progress bar width:
var par1 = 4;
for(var i = 10; i < 16; i++) {
$('.p' + (i+1)).text(table[0][par1]);
$('.bar' + (i+1)).css("width", table[0][par1]);
par1++;
}
How could I make it more responsive? Thank you in advance!
I recommend using css flexbox, so the items wrap instead of overlap when the page is resized. You could use media queries with this to adjust the size of the items and container so they don't overlap/wrap. This site has a good explanation of flexbox: A Complete Guide to Flexbox.

CSS display a hidden drop-up menu on mobile

I have a drop-up footer that is working great :
$('#drop-up-open').click(function() {
$('#drop-up #drop-upDashboard').slideToggle({
direction: "up"
}, 300);
$(this).toggleClass('drop-upClose');
}); // end click
#drop-up {
position: absolute;
bottom: 0;
width: 100%;
padding-bottom: 4%;
z-index: 100;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
}
#drop-up-open {
cursor: pointer;
text-decoration: none;
}
#drop-up .drop-upClose {}
#drop-up #drop-upDashboard {
display: none;
}
#media screen and (max-width: 1000px) {
#drop-up #drop-upDashboard{
display:block; }
}
<div class="container">
<!-- Jumbotron Header -->
<header class="jumbotron panel-heading">
<p class="text-center">
Text getting covered by drop-up menu on mobile
</p>
<section>
<button> Main button </button>
</section>
</header>
<div id="drop-up">
Open
<div id="drop-upDashboard">
<p>It's now open!</p>
<div class="row">
<div class="col-md-3 col-xs-12">
<section> <a href="#"><button>
<p>Button 1</p>
</button></a> </section>
</div>
<div class="col-md-3 col-xs-12">
<section> <a href="#"><button>
<p>Button 2</p>
</button></a> </section>
</div>
<div class="col-md-3 col-xs-12">
<section> <a href="#"><button>
<p>Button 3</p>
</button></a> </section>
</div>
<div class="col-md-3 col-xs-12">
<section> <a href="#"><button>
<p>Button 4</p>
</button></a> </section>
</div>
</div>
<!-- row -->
</div>
<!-- dashboard -->
</div>
<!-- drop-up -->
</div>
<!-- container -->
When I click the id="drop-up" div, the menu opens from bottom to top and occupies a small portion of the bottom of the window on desktop view.
Now, what I want is that this menu which is at first hidden on desktop view, gets displayed on smaller devices (mobile+tablet) without having to click the id="drop-up" div. It would occupy the same portion of the bottom of the page on mobile+tablet (and the user would then need to scroll down to see the drop-up menu on smaller devices, which is not the case on desktop view).
Any suggestions/tips about the best method to achieve this ?
You could wrap the whole thing in a flex box, then have the body flex to fill up the rest of the space, thus putting your footer at the footer level. Also 'appears' to work when you go responsive.
HOWEVER, this feels quite hacky at the moment, as if you draw a border around the flex box container, it'll only fit at its original 100% level.
$('#drop-up-open').click(function() {
$('#drop-up #drop-upDashboard').slideToggle({
direction: "up"
}, 300);
$(this).toggleClass('drop-upClose');
}); // end click
html, body {
height: 100%;
}
#drop-up-open {
cursor: pointer;
text-decoration: none;
}
#drop-up .drop-upClose {}
#drop-up #drop-upDashboard {
display: none;
}
#media screen and (max-width: 200px) {
#drop-up #drop-upDashboard{
display:block; }
html, body {
height: auto !important;
}
}
.container {
display: flex;
flex-direction: column;
border: 1px solid black;
min-height: 100%;
}
.body {
flex: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<!-- Jumbotron Header -->
<header class="jumbotron panel-heading" style="background-color: yellow; opacity: 0.7">
<p class="text-center">
Text getting covered by drop-up menu on mobile
</p>
<section>
<button> Main button </button>
</section>
</header>
<div class="body" style="background-color: orange; opacity: 0.3">
a body
</div>
<div id="drop-up" style="background-color: lightblue; opacity: 0.7">
Open
<div id="drop-upDashboard">
<p>It's now open!</p>
<div class="row">
<div class="col-md-3 col-xs-12">
<section> <a href="#"><button>
<p>Button 1</p>
</button></a> </section>
</div>
<div class="col-md-3 col-xs-12">
<section> <a href="#"><button>
<p>Button 2</p>
</button></a> </section>
</div>
<div class="col-md-3 col-xs-12">
<section> <a href="#"><button>
<p>Button 3</p>
</button></a> </section>
</div>
<div class="col-md-3 col-xs-12">
<section> <a href="#"><button>
<p>Button 4</p>
</button></a> </section>
</div>
</div>
<!-- row -->
</div>
<!-- dashboard -->
</div>
<!-- drop-up -->
</div>
<!-- container -->

Reorder columns for mobile devices with Bootstrap

I have a web application which was created for desktops and now we are trying to utilize Twitter Bootstrap to make it responsive. We have few sidebar layouts where we want them to collapse in order different from their actual order. Right now when viewing on mobile phone left column is shown on top of content column. We want to show content on top for mobile device. I know about push-pull classes in twitter bootstrap but that doesn't seems to work unless I make changes to HTML. We can't change the HTML since there are other legacy themes which will break. Any help will be appreciated.
Updated: Here is the jsfiddle to reproduce the issue. As you can see it results in Blue sidebar on Green content column and I want the exact inverse of it where Green should be on top of Blue column.
<div id="outerPageContainer" class="container">
<div id="innerPageContainer">
<div id="header" class="row">
<div class="zone col-md-12 alert alert-warning">
Header
</div>
</div>
<div id="contentContainer" class="row">
<div id="leftColumn" class="col-md-3">
<div class="zone alert alert-info">
Sidebar
</div>
</div>
<div id="mainColumn" class="leftSidebarLayout col-md-9">
<div class="zone alert alert-success">
Content
</div>
</div>
</div>
<div id="footer" class="row">
<div class="zone col-md-12 alert alert-warning">
Footer
</div>
</div>
</div>
</div>
http://jsfiddle.net/4z7bq8ft/5/embedded/result/
Kind Regards
Bootstrap alredy brings responsive design, but only to 768px (Ipad width). You can use this bootstrap functionality with their column system:
.col-xs- to <768px .col-sm- to ≥768px .col-md- to ≥992px and .col-lg- to ≥1200px
there is more info in the web: http://getbootstrap.com/css/
If you want responsive design below 768 you will need to do it yourself by using:
#media (mix-width: 600px, max-width: 768px) for example.
Try the method bellow and order as needed.
.plate {
display: flex;
flex-direction: row;
}
.one, .two, .three, .four, .five {
width: 100px;
height: 100px;
display: inline-block;
text-align: center;
line-height: 100px;
font-weight: bold;
color: white;
font-size: 24px;
}
.one {
background-color: red;
order: 2;
}
.two {
background-color: green;
order: 3;
}
.three {
background-color: orange;
order: 1;
}
.four {
background-color: darkorange;
order: 5;
}
.five {
background-color: orange;
order: 4;
}
<div class="plate">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
<div class="four">Four</div>
<div class="five">Five</div>
</div>
See CSS Flexible Box Layout Module
Try this : http://jsfiddle.net/4z7bq8ft/9/
and html & css code is here
<form id="form1" runat="server">
<div id="outerPageContainer" class="container">
<div id="innerPageContainer">
<div id="header" class="row">
<div class="zone col-sm-12 alert alert-warning">
Header
</div>
</div>
<div id="contentContainer" class="row">
<div id="mainColumn" class="leftSidebarLayout col-sm-9">
<div class="zone alert alert-success">
Content
</div>
</div>
<div id="leftColumn" class="col-sm-3">
<div class="zone alert alert-info">
Sidebar
</div>
</div>
</div>
<div id="footer" class="row">
<div class="zone col-sm-12 alert alert-warning">
Footer
</div>
</div>
</div>
</div>
</form>
.col-sm-9 {
float: right !important;
width: 75%;
}
#media screen and (max-width:768px) {
.col-sm-9 {
width: 100%;
}
.col-sm-3 {
float: left;
width: 100%;
}
}

Categories