create markup sections bases on height of divs using jquery - javascript

I have multiple number of divs with class .row, I want to copy all those divs in sections with respective of their heights , Maximum height for each section should be 1100px, I want to copy all the divs in different sections and if section height reaches 1100 pixel then new section should be created, please see below example:
<div class="row row1">
<p>some html tables and paragraphs here </p>
</div>
<div class="row row2">
<p>some html tables and paragraphs here </p>
</div>
<div class="row row3">
<p>some html tables and paragraphs here </p>
</div>
<div class="row row4">
<p>some html tables and paragraphs here </p>
</div>
In the above example first of all I should get the heights of all divs then I should make the calculation and create sections using jQuery.
Let suppose .row1 has 700px height, .row2 is 900px , .row3 is 300px and .row4 is 100px.
So the resultant sections should be generated like this
<section>
<div class="row row1">
<p>some html tables and paragraphs here </p>
</div>
<div class="row row3">
<p>some html tables and paragraphs here </p>
</div>
<div class="row row4">
<p>some html tables and paragraphs here </p>
</div>
</section>
<section>
<div class="row row2">
<p>some html tables and paragraphs here </p>
</div>
</section>
each section should not exceed the height of 1100px.
I want to print each section with 1100px on separate Legal Page, I don't want to have more than 1100px section.
I would appreciate if anyone can implement this logic.

Consider the following.
$(function() {
function makeSection() {
return $("<section>").insertAfter($("section:last"));
}
function checkHeight(a, b, h) {
if (h == undefined) {
h = 1100;
}
var r = a + b;
return r > h;
}
$("section:first .row").each(function(i, el) {
var t = $("section:first .row").length;
if (i < t) {
if (checkHeight($(el).height(), $(el).next().height())) {
var nextSection = makeSection();
nextSection.append($(el).next().detach());
}
}
});
});
section {
border: 1px solid #999;
padding: 3px;
}
section .row {
border: 1px solid #ccc;
}
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<section>
<div class="row row1" style="height: 700px;">
<p>Item 1</p>
</div>
<div class="row row2" style="height: 900px;">
<p>Item 2</p>
</div>
<div class="row row3" style="height: 300px;">
<p>Item 3</p>
</div>
<div class="row row4" style="height: 100px;">
<p>Item 4</p>
</div>
</section>
Here you can see we have some smaller helper functions. checkHeight will calculate the combined height values. If they are less then the threshold h (defaulting to 1100), it returns false. If it is more than the threshold, it return true.
You can then iterate each of the rows and get the height from each. 1 & 2, 2 & 3, 3 & 4. If too high, the second section is moved to a new one.

Related

Set height to the lowest height of the sibling child div

I have multiple rows, every row has multiple columns, in each column i have a div + a paragraphe, the div includes an image. i need to set the div with the class cover-bg to the lowest height of cover-bg in the same row the calculated height of the cover-bg in the first row can't be the same height in the second row
<div class="row">
<div class="col-md-4">
<div class="cover-bg"><img src="url"></div>
<p>text here</p>
</div>
<div class="col-md-6">
<div class="cover-bg"><img src="url"></div>
<p>text here</p>
</div>
</div>
<div class="row">
<div class="col-md-5">
<div class="cover-bg"><img src="url"></div>
<p>text here</p>
</div>
<div class="col-md-4">
<div class="cover-bg"><img src="url"></div>
<p>text here</p>
</div>
</div>
I have tried this but it sets the lowest height of all the rows :
var minHeight = Math.min.apply(null, $('.cover-bg').map(function(){return $(this).height()}));
$('.cover-bg').height(minHeight);
I am having trouble manipulating the siblings() and children()
The problem is how to separate and set the height for each row
You'll need to set an image height for each row otherwise all will have the same height.
I got a bit confused with the suggested jquery so here is a snippet which spells it out in pure JS.
For each row it finds the minimum image height and then sets a CSS variable property of that row to that height. This is used to style each of the images in that particular row.
<!doctype html>
<html>
<head>
<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/bootstrap/5.0.2/css/bootstrap.min.css">
<style>
.row {
margin-bottom: 20px;
}
.row .cover-bg img:first-child {
height: calc(var(--h) * 1px);
}
</style>
</head>
<body>
<div class="row">
<div class="col-md-4">
<div class="cover-bg"><img src="https://picsum.photos/id/1015/200/500"></div>
<p>
weofijae
<br/> weofjiawef awoeifj awoefij
</p>
</div>
<div class="col-md-6">
<div class="cover-bg"><img src="https://picsum.photos/id/1016/200/1000"></div>
<p>text here</p>
</div>
</div>
<div class="row">
<div class="col-md-5">
<div class="cover-bg"><img src="https://picsum.photos/id/1015/200/300"></div>
<p>text here</p>
</div>
<div class="col-md-4">
<div class="cover-bg"><img src="https://picsum.photos/id/1016/200/200"></div>
<p>text here</p>
</div>
</div>
<script>
function start() {
const rows = document.querySelectorAll('.row');
rows.forEach(row => {
const imgs = row.querySelectorAll('img');
let heights = [];
imgs.forEach(img => {
heights.push(img.height);
});
row.style.setProperty('--h', Math.min.apply(null, heights));
});
}
window.onload = start;
</script>
</body>
</html>
Note: you need to wait til the images are loaded before getting their natural heights.
Run the snippet full page otherwise the rows may wrap.
Try this:
var minHeight = Math.min(...$.map($('.cover-bg'), (e) => ($(e).height())));
$('.cover-bg').height(minHeight);
Here is the example.

Determining if a child div has content

I'm working with some code that allows content editors to add content. I've found a few instances where there is a div that has children (like h5 or p) but no text. The div is taking up space and I would like to remove all of the divs that have no actual text in it.
The only thing I've found is the :empty css selector, but that checks for children, not text.
$('.col-lg-4:empty').remove();
.col-lg-4 {
background-color: #c8c8c8;
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
<div class="col-lg-4">
<h5 class="headline1">Test Title</h5>
<p class="p2"></p>
<p>This is some filler text that I have added for testing purposes.This is some filler text that I have added for testing purposes.This is some filler text that I have added for testing purposes.</p>
<p></p>
</div>
<div class="col-lg-4">
<h5 class="subtitle1"></h5>
<p class="p2"></p>
</div>
<div class="col-lg-4">
<p class="p2 last-column"></p>
</div>
<div class="col-lg-4"></div>
</div>
This is some real content from my site that editors have added. As you can see, I have unnecessary divs with no content (the .col-lg-4 ones) that I would like to get rid of. With the :empty, it removes the last one that has no children. But what would be the best way to remove the ones that have children that have no content?
Is that what you want to do?
I can't think of an easier way to do it!
Check the snippet:
$('.col-lg-4').each(function() {
if (!this.innerText) $(this).remove();
});
.col-lg-4 {
background-color: #c8c8c8;
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="row">
<div class="col-lg-4">
<h5 class="headline1">Test Title</h5>
<p class="p2"></p>
<p>This is some filler text that I have added for testing purposes.This is some filler text that I have added for testing purposes.This is some filler text that I have added for testing purposes.</p>
<p></p>
</div>
<div class="col-lg-4">
<h5 class="subtitle1"></h5>
<p class="p2"></p>
</div>
<div class="col-lg-4">
<p class="p2 last-column"></p>
</div>
<div class="col-lg-4"></div>
</div>
I used innerText to get rid of all the html tags.
Hope it helps.
Iterate over them, check for empty children, remove:
$('.col-lg-4').each(function () {
if ($(this).children().text() == '') $(this).remove();
});
Without jQuery:
Array.from(document.querySelectorAll('.col-lg-4'))
.filter(i => !i.innerText)
.forEach(e => e.parentNode.removeChild(e));

Three columns with equal height corresponding rows in each column

I need to create a layout in which you have three columns, in each column the corresponding row needs to have the same height. The requirements for this are.
Three columns
Inside each column there are multiple rows.
Each corresponding row must be the same height.
On mobile the columns will turn into a slider.
I've considered 2 layout options for this.
target each row in each column and set the height with Javascript
<div class="container">
<div class="col">
<div class="row">row 1</div>
<div class="row">row 2</div>
<div class="row">row 3</div>
</div>
<div class="col">
<div class="row">row 1</div>
<div class="row">row 2</div>
<div class="row">row 3</div>
</div>
<div class="col">
<div class="row">row 1</div>
<div class="row">row 2</div>
<div class="row">row 3</div>
</div>
</div>
This layout is ideal as I can target the column and add the drop shadow styles without having to target each row and apply to each one. Implementing the slider on mobile would be easier as there is three container columns. But, looping through each column and getting the corresponding row and updating the height on each one seems like a lot of work especially since the height will need to be recalculated every time there is an api call (there's filter above with allow you to update the data).
Use flex
<div class="container">
<div class="row">
<div class="col">
row 1 col 1
</div>
<div class="col">
row 1 col 2
</div>
<div class="col">
row 1 col 3
</div>
</div>
<div class="row">
<div class="col">
row 2 col 1
</div>
<div class="col">
row 2 col 2
</div>
<div class="col">
row 2 col 3
</div>
</div>
<div class="row">
<div class="col">
row 3 col 1
</div>
<div class="col">
row 3 col 2
</div>
<div class="col">
row 3 col 3
</div>
</div>
</div>
This approach is appealing because I don't need to use JS to set the height of each corresponding row in each column. But, i'll need to set the individual styles like drop shadows to each row which means i'll need to use all sorts of trickery so as not to apply the drop shadow to the top and bottom of each row, there's also the risk that this will not display correctly in different browsers (needs to go back as far as IE 10). Also the only slider effect i'll be able to active is overflow scroll which doesn't fit the requirments.
So, my questions are, are there other options i'm not considering? What would you do?
I would consider option 1 for the following reasons:
Your markup is semantically correct (3 columns, each with some rows) and clean
Your column styles can easily be applied
Looping through all rows just to calculate the maximum height isn't that cumbersome especially if you only have a few rows.
A solution with vanilla JavaScript could look like the following. You can wrap the code into a function and call it, whenever your filter is applied:
var rows = document.querySelectorAll(".col:nth-child(1) > .row").length, n
for (n = 1; n <= rows; ++n) {
var cells = document.querySelectorAll('.row:nth-child(' + n + ')')
var maxHeight = 0, i
for (i = 0; i < cells.length; ++i) {
maxHeight = (cells[i].clientHeight > maxHeight) ? cells[i].clientHeight : maxHeight
}
cells.forEach(function(cell){
cell.style.height = Number(maxHeight-10) + 'px'
})
}
.col {
display: inline-block;
width: calc(33% - 41px);
margin: 10px 10px;
padding: 10px;
border-radius: 15px;
box-shadow: 0 0 20px #aaa;
vertical-align: top;
}
.row {
border-top: 3px solid black;
margin: 5px 0;
padding: 5px;
}
<div class="container">
<div class="col">
<div class="row">row 1 Compare text 1</div>
<div class="row">row 2</div>
<div class="row">row 3</div>
</div>
<div class="col">
<div class="row">row 1 Compare text 1 this text is longer</div>
<div class="row">row 2</div>
<div class="row">row 3 with a little more text</div>
</div>
<div class="col">
<div class="row">row 1 Compare text 1 this text is even much much longer</div>
<div class="row">row 2</div>
<div class="row">row 3</div>
</div>
</div>

How can I reorder vertical columns in Bootstrap?

I wan to know if it's possible to re-order vertical columns on Bootstrap 3.
.col-xs-8 {
background: magenta;
}
.col-xs-4 {
background: cyan;
}
.col-xs-12 {
background: yellow;
}
<div class="container">
<div class="row">
<div class="col-xs-8">Content</div>
<div class="col-xs-4">
<div class="row">
<div class="col-xs-12 col-xs-push-12">A</div>
<div class="col-xs-12">B</div>
<div class="col-xs-12">C</div>
<div class="col-xs-12">D</div>
</div>
</div>
</div>
</div>
JSFiddle
What I want it's to move the items on the sidebar from ABCD to BCAD
What you want to achieve can not be done for responsive layout.....but assuming you have static content then, it can be done using margins :
Here is a demo
Wrap your ordering divs in some parent div and apply responsive layout to it....in the demo, i have dome that through abcd class ( its not responsive though since its in pixels)
HTML
<div class="abcd">
<div class="col-xs-12 " style="margin-top:-110px;color:#000">A</div>
<div class="col-xs-12" style="margin-top:-150px;color:#000">B</div>
<div class="col-xs-12" style="margin-top:-130px;color:#000">C</div>
<div class="col-xs-12" style="margin-top:-90px;color:#000">D</div>
<div>
EDIT :
demo with percentage value
In %ge, you can vreate something like :
<div class="abcd">
<div class="col-xs-12" style="margin-top:-13%;color:#000;">A</div>
<div class="col-xs-12" style="margin-top:-33%;color:#000">B</div>
<div class="col-xs-12" style="margin-top:-23%;color:#000">C</div>
<div class="col-xs-12" style="margin-top:-3%;color:#000">D</div>
<div>
CSS
.abcd {
margin-top:33%;/* keep this equal to margin of B, but with opposite sign */
}
Assuming you have to insert first child just before the last child.
You can do it with jquery. See Demo
$( ".flexbox div:first" ).append().insertBefore( ".flexbox div:last" );

How do I move identical elements from one div to another with jQuery?

With the example below, I'd like to select the contents of the < h3 > tags for each block, and move them inside the 'title' divs (without the h3 tags). Is this possible?
<div id="block1">
<div class="title">
</div>
<div class="content">
<h3>Title 1</h3>
</div>
</div>
<div id="block2">
<div class="title">
</div>
<div class="content">
<h3>Title 2</h3>
</div>
</div>
Online demo: http://jsbin.com/ezuxo
// Cycle through each <div class="content"></div>
$(".content").each(function(){
// Find its first h3 tag, and remove it
var heading = $("h3", this).remove();
// Set the text of the h3 tag to the value of the previous div (.title)
$(this).prev().html($(heading).html());
});
First off, I'd assign a class to the "blocks", let's call it "block" for now. Then do this:
$(".block").each(function() {
$(".title", this).html($(".content h3", this).html());
}

Categories

Resources