Wrap groups of elements using jQuery - javascript

I've got a list of elements and I want to group them with div starting with the first element and ends with BREAK class then start a new group after the class BREAK.
So the code below,
<div class="test">Test 0</div>
<div class="test">Test 1</div>
<div class="break">Break 0</div>
<div class="test">Test 2</div>
<div class="test">Test 3</div>
<div class="break">Break 1</div>
<div class="test">Test 4</div>
<div class="test">Test 5</div>
<div class="test">Test 6</div>
Would become,
<div>
<div class="group">
<div class="test">Test 0</div>
<div class="test">Test 1</div>
<div class="break">Break 0</div>
</div>
<div class="group">
<div class="test">Test 2</div>
<div class="test">Test 3</div>
<div class="break">Break 1</div>
</div>
<div class="group">
<div class="test">Test 4</div>
<div class="test">Test 5</div>
<div class="test">Test 6</div>
<div class="break">Add last break element</div>
</div>
<div>
And append a div element in the last group.
Any ideas? Thanks in advance.

I'd probably go with simple: Loop through them with a container you add to, add a new container every time you see break:
var div;
$("selector for the divs").each(function() {
if (!div) {
div = $("<div>").insertBefore(this);
}
div.append(this);
if ($(this).hasClass("break")) {
div = undefined;
}
});
if (div) {
$("<div>last break</div>").addClass("break").appendTo(div);
}
Example (I added a wrapper class so we could see the effect when adding):
$("#go").click(function() {
var div;
$("#container > div").each(function() {
if (!div) {
div = $("<div>").addClass("wrapper").insertBefore(this);
}
div.append(this);
if ($(this).hasClass("break")) {
div = undefined;
}
});
if (div) {
$("<div>last break</div>").addClass("break").appendTo(div);
}
});
.test {
color: blue;
}
.break {
color: red;
}
.wrapper {
border: 1px solid #aaa;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="button" id="go" value="Go">
<div id="container">
<div class="test">Test 0</div>
<div class="test">Test 1</div>
<div class="break">Break 0</div>
<div class="test">Test 2</div>
<div class="test">Test 3</div>
<div class="break">Break 1</div>
<div class="test">Test 4</div>
<div class="test">Test 5</div>
<div class="test">Test 6</div>
</div>

I think you can also do something like this: first you insert one more .break to all .test parent container, then using wrapAll method wrap groups properly:
$('.test').parent().append('<div class="break">Break 2</div>').
find('.test + .break').each(function() {
$(this).prevUntil('.break, .group').add(this).wrapAll('<div class="group"></div>');
});
.group {
padding: 3px;
background: #BFECBE;
margin-bottom: 2px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="test">Test 0</div>
<div class="test">Test 1</div>
<div class="break">Break 0</div>
<div class="test">Test 2</div>
<div class="test">Test 3</div>
<div class="break">Break 1</div>
<div class="test">Test 4</div>
<div class="test">Test 5</div>
<div class="test">Test 6</div>
</div>

this code is working fine,you can check the fiddle and demo here as well
$("div.test").each(function() {
if (!$(this).nextAll(".break").length)
$(".test").last().after('<div class="break">Add last break element</div>');
if (!$(this).parents(".group").length)
$(this).add($(this).nextUntil('.break+.test').andSelf()).wrapAll('<div class="group" />');
});
.group {
background: red;
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">Test 0</div>
<div class="test">Test 1</div>
<div class="break">Break 0</div>
<div class="test">Test 2</div>
<div class="test">Test 3</div>
<div class="break">Break 1</div>
<div class="test">Test 4</div>
<div class="test">Test 5</div>
<div class="test">Test 6</div>
});
Fiddle Demo

Related

Rearrange divs - Place each div under each image (javascript - jQuery)

I have the following structure example:
<div class="main">
<div class="image">Image1</div>
<div class="image">Image2</div>
<div class="image">Image3</div>
</div>
<div class="side">
<div class="Banner">Banner1</div>
<div class="Banner">Banner2</div>
<div class="Banner">Banner3</div>
<div class="Banner">Banner4</div>
</div>
I want to make a script that will take each banner and placed under each image.
<div class="main">
<div class="image">Image1</div>
<div class="Banner">Banner1</div>
<div class="image">Image2</div>
<div class="Banner">Banner2</div>
<div class="image">Image3</div>
<div class="Banner">Banner3</div>
<div class="Banner">Banner4</div>
</div>
<div class="side"></div>
Basically there are some images placed one after another and then some banners placed one after another.
Image1
Image2
Image3
Banner1
Banner2
Banner3
Banner4
I need to take each banner and place it under each image so I can have:
Image1
Banner1
Image2
Banner2
Image3
Banner3
Banner4
I cannot change the html to manually placed the banners, I need to use a more advanced script JS and or jquery ..
.content {display:flex; max-width:800px;min-width:300px;gap:20px;margin:auto;}
.main { flex: 70%;}.main2 {max-width:400px;}
.side { flex: 30%; padding:10px;}.img { background:blue;}.banner { background:red;}
.img, .banner { width:100%; min-width:50px; height:50px;display:grid;place-items:center; color: #fff; margin:10px auto;}
<h2>Rearrange content - Place each div (banner) under each image </h2>
<div class="content">
<div class="main">
<div class="img">Image 1</div>
<div class="img">Image 2</div>
<div class="img">Image 3</div>
<div class="img">Image 4</div>
<div class="img">Image 5</div>
<div class="img">Image 6</div>
<p> Multiple DIVs with images ...
<br> ...
</div>
<div class="side">
<div class="banner">Banner1</div>
<div class="banner">Banner2</div>
<div class="banner">Banner3</div>
<div class="banner">Banner4</div>
<div class="banner">Banner5</div>
<div class="banner">Banner6</div>
<div class="banner">Banner7</div>
<div class="banner">Banner8</div>
<div class="banner">Banner9</div>
<div class="banner">Banner10</div>
</div>
</div>
<hr>
<h2> This is how it should look </h2>
<div class="main2">
<div class="img">Image 1</div>
<div class="banner">Banner1</div>
<div class="img">Image 2</div>
<div class="banner">Banner2</div>
<div class="img">Image 3</div>
<div class="banner">Banner3</div>
<div class="img">Image 4</div>
<div class="banner">Banner4</div>
<div class="img">Image 5</div>
<div class="banner">Banner5</div>
<div class="img">Image 6</div>
<div class="banner">Banner6</div>
<div class="banner">Banner7</div>
<div class="banner">Banner8</div>
<div class="banner">Banner9</div>
<div class="banner">Banner10</div>
</div>
To do what you require you can loop through the .banner elements and use their index to place them underneath the related .img element by their indexes using insertAfter(). Something like this:
let $imgs = $('.content .main .img');
$('.content .side .banner').each((i, el) => $(el).insertAfter($imgs[i]));
.content {
display: flex;
max-width: 800px;
min-width: 300px;
gap: 20px;
margin: auto;
}
.main {
flex: 70%;
}
.img,
.banner {
width: 100%;
min-width: 50px;
height: 50px;
display: grid;
place-items: center;
color: #fff;
margin: 10px auto;
}
.img {
background: blue;
}
.banner {
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="main">
<div class="img">Image 1</div>
<div class="img">Image 2</div>
<div class="img">Image 3</div>
<div class="img">Image 4</div>
<div class="img">Image 5</div>
<div class="img">Image 6</div>
</div>
<div class="side">
<div class="banner">Banner1</div>
<div class="banner">Banner2</div>
<div class="banner">Banner3</div>
<div class="banner">Banner4</div>
<div class="banner">Banner5</div>
<div class="banner">Banner6</div>
</div>
</div>
Well, to answer my own question, it was hard for me since I don't know JS that well.
I managed to make something that also randomizes the banners and I've used jquery.
jQuery("#btn").click(function() {
var cards = jQuery(".side .banner");
for(var i = 0; i < cards.length; i++){
var target = Math.floor(Math.random() * cards.length -1) + 1;
var target2 = Math.floor(Math.random() * cards.length -1) +1;
cards.eq(target).before(cards.eq(target2));
}
cards = jQuery(".side .banner");
var images = jQuery(".content.desk .img");
if (cards.length < images.length) {
for (var i=0; i<cards.length; i++) {
images.eq(i).after(cards.eq(i));
}
} else {
for (var i=0; i<images.length; i++) {
images.eq(i).after(cards.eq(i))
}
for (var i=images.length; i<cards.length; i++){
cards.eq(i-1).after(cards.eq(i));
}
}
});
body {
max-width:1250px;
margin:auto;
}
h1, h2, h3, h4 {
text-align:center;
}
.content {
display:flex;
max-width:800px;
min-width:300px;
gap:20px;
margin:auto;
}
.main {
flex: 70%;
}
.side {
flex: 30%;
background: lightblue;
padding:10px;
}
.img {
background:blue;
}
.banner {
background:red;
}
.img, .banner {
width:100%;
min-width:50px;
height:50px;
display:grid;
place-items: center;
color: #fff;
margin:10px auto;
}
<body>
<h1>Rearrange content</h1>
<div class="content desk">
<div class="main">
<button id="btn">Click to reorder and randomize</button>
<div class="img">Image 1</div>
<div class="img">Image 2</div>
<div class="img">Image 3</div>
<div class="img">Image 4</div>
<div class="img">Image 5</div>
<div class="img">Image 6</div>
<div class="img">Image 7</div>
<div class="img">Image 8</div>
<div class="img">Image 9</div>
<div class="img">Image 10</div>
<div class="img">Image 11</div>
<div class="img">Image 12</div>
<div class="img">Image 13</div>
</div>
<div class="side">
<div class="banner">Banner1</div>
<div class="banner">Banner2</div>
<div class="banner">Banner3</div>
<div class="banner">Banner4</div>
<div class="banner">Banner5</div>
<div class="banner">Banner6</div>
<div class="banner">Banner7</div>
<div class="banner">Banner8</div>
<div class="banner">Banner9</div>
<div class="banner">Banner10</div>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"></script>
</body>
Edit:
Here's another method that's a bit more concise.
const main = document.querySelectorAll('.main .img');
const side = document.querySelectorAll('.side .banner');
let offset;
side.forEach((banner, idx) => {
const img = main[idx] || offset;
img.insertAdjacentElement('afterend', banner);
offset = banner;
});
.content { display: flex }
.main, .side { flex-grow: 1 }
.content,
.main2 {
font-family: sans-serif;
line-height: 2;
color: white;
}
.img { background-color: red; margin: 3px;}
.banner { background-color: blue; margin: 3px;}
<div class="body">
<h2>Rearrange content - Place each div (banner) under each image </h2>
<div class="content">
<div class="main">
<div class="img">Image 1</div>
<div class="img">Image 2</div>
<div class="img">Image 3</div>
<div class="img">Image 4</div>
<div class="img">Image 5</div>
<div class="img">Image 6</div>
</div>
<div class="side">
<div class="banner">Banner1</div>
<div class="banner">Banner2</div>
<div class="banner">Banner3</div>
<div class="banner">Banner4</div>
<div class="banner">Banner5</div>
<div class="banner">Banner6</div>
<div class="banner">Banner7</div>
<div class="banner">Banner8</div>
<div class="banner">Banner9</div>
<div class="banner">Banner10</div>
</div>
</div>
</div>
Original:
You need to loop over the elements and then merge/combine the arrays as you are looping. There are multiple ways this can be done. Here's one way (with comments) that uses reduce to combine the elements.
If you're starting out with JS, I would suggest using a simple for loop to start off.
When you run the code snippet below, the original will be in Red. Clicking the button will merge the elements, append them, and display them in Green.
Good luck!
// I've wrapped this in a function so I can call it.
function rearrange() {
// First I'm going to query all the divs with 'img' class
// From that, I'll call 'Array.from' to create an array.
const images = Array.from(document.querySelectorAll('.img'));
// Similar to above, but for all the 'banner' divs.
const banners = Array.from(document.querySelectorAll('.banner'));
// This is my loop. I'm using .reduce, but for/while/.forEach/etc
// would all have worked.
// I'm going to loop over the images and push image/banner into
// a new container
const container = images.reduce(function (el, image) {
// get the first "banner" div
const banner = banners.shift();
// append the image div, first
el.appendChild(image);
// if a banner exists, append that
if (banner) {
el.appendChild(banner);
}
// as this is a reducer, i return my accumulator of divs
return el;
}, document.createElement('div'));
// As image/banner could differ in length, push any additional
// banner divs to the container
if (banners.length > 0) {
banners.forEach(banner => container.appendChild(banner));
}
// Add the new class name
container.classList.add('main2');
// Finally, append to body
document.querySelector('.body').appendChild(container);
}
// My event handler to run
document.querySelector('#rearrange').addEventListener('click', rearrange);
.content { display: flex }
.main, .side { flex-grow: 1 }
.content,
.main2 {
font-family: sans-serif;
line-height: 2;
color: white;
}
.img { background-color: red; margin: 3px;}
.banner { background-color: blue; margin: 3px;}
<div class="body">
<button id="rearrange">Click here to re-arrange</button>
<h2>Rearrange content - Place each div (banner) under each image </h2>
<div class="content">
<div class="main">
<div class="img">Image 1</div>
<div class="img">Image 2</div>
<div class="img">Image 3</div>
<div class="img">Image 4</div>
<div class="img">Image 5</div>
<div class="img">Image 6</div>
</div>
<div class="side">
<div class="banner">Banner1</div>
<div class="banner">Banner2</div>
<div class="banner">Banner3</div>
<div class="banner">Banner4</div>
<div class="banner">Banner5</div>
<div class="banner">Banner6</div>
<div class="banner">Banner7</div>
<div class="banner">Banner8</div>
<div class="banner">Banner9</div>
<div class="banner">Banner10</div>
</div>
</div>
<h2>Rearranged:</h2>
<hr />
</div>

How to delete first row of inline-block divs

I have a bunch of inline-block divs on my web page,
<div class="container">
<div class="text">Text 1</div>
<div class="text">Text 2</div>
<div class="text">Text 3</div>
<div class="text">Text 4</div>
<div class="text">Text 5</div>
<div class="text">Text 6</div>
<div class="text">Text 7</div>
</div>
and they wrap around like this:
I want to be able to delete the first row of them, that is in this case 1-5. But if I scale this to where only 1-3 are in the first row, I would only like to delete those. (you get it)
I don't have any clue what kind of javascript can be applied for this particular use case, but for simplicity, heres the JSFiddle. I would rather not use JQuery.
If the width of each item is the same, you can get the width of container, divide by the width of each item (to determine the number of items in each row), then delete that many items from the start.
const item = document.querySelector('.text');
const itemWidth = item.offsetWidth + 2 * parseFloat(window.getComputedStyle(item).getPropertyValue("margin"));
const containerWidth = document.querySelector('.container').offsetWidth;
const itemsInFirstRow = Math.floor(containerWidth / itemWidth);
document.querySelectorAll('.text').forEach((e,i) => {
if(i < itemsInFirstRow) e.remove()
})
.text {
height: 50px;
width: 50px;
background-color: red;
display: inline-block;
margin: 5px;
color: white;
text-align: center;
}
.container{
width:200px;
}
<div class="container">
<div class="text">Text 1</div>
<div class="text">Text 2</div>
<div class="text">Text 3</div>
<div class="text">Text 4</div>
<div class="text">Text 5</div>
<div class="text">Text 6</div>
<div class="text">Text 7</div>
</div>

Show and Hide Div With Matching Class Name On Click

I am still getting to grips with jQuery and wondered if anyone had a suggestion for this?
Basically on click I want to show the div with the matching class, so if you click the btn with class '.project1' then it should show the content div with the same class of '.project1'.
I'm just stuck on how it would find this so any suggestions would be awesome :)
Thanks in advance.
Snippet:
$('div[class*="project"]').click(function (e) {
$(this).closest('.content').show();
});
.content {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="project1 btn">BTN 1</div>
<div class="project2 btn">BTN 2</div>
<div class="project3 btn">BTN 3</div>
<div class="project4 btn">BTN 4</div>
<div class="project1 content">CONTENT 1</div>
<div class="project2 content">CONTENT 2</div>
<div class="project3 content">CONTENT 3</div>
<div class="project4 content">CONTENT 4</div>
CodePen: https://codepen.io/nickelse/pen/mYrOdz?editors=1111
One option is to use data() to store arbitrary data associated with the matched elements or return the value at the named data store for the first element in the set of matched elements.
$('div[class*="project"]').click(function (e) {
var project = $(this).data("project"); //Get the data-project of the clicked element
$(".content.project" + project).toggle(); //Toggle the element with content and project class
});
.content {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="project1 btn" data-project="1">BTN 1</div> <!-- Add data-project on HTML-->
<div class="project2 btn" data-project="2">BTN 2</div>
<div class="project3 btn" data-project="3">BTN 3</div>
<div class="project4 btn" data-project="4">BTN 4</div>
<div class="project1 content" data-project="1">CONTENT 1</div>
<div class="project2 content" data-project="2">CONTENT 2</div>
<div class="project3 content" data-project="3">CONTENT 3</div>
<div class="project4 content" data-project="4">CONTENT 4</div>
You need to find the project number you clicked on.
You can do that by filtering the classes of the button you clicked on and extracting the number :
+[...this.classList].find(c => c.startsWith('project')).replace('project', '');
Then all you have to do is toggle the targeted project content :
$('.content.project'+project).toggle();
Here's a working example:
$('div[class^="project"]').on('click', function(){
const project = +[...this.classList].find(c => c.startsWith('project')).replace('project', '');
$('.content.project'+project).toggle();
});
.content {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="project1 btn">BTN 1</div>
<div class="project2 btn">BTN 2</div>
<div class="project3 btn">BTN 3</div>
<div class="project4 btn">BTN 4</div>
<div class="project1 content">CONTENT 1</div>
<div class="project2 content">CONTENT 2</div>
<div class="project3 content">CONTENT 3</div>
<div class="project4 content">CONTENT 4</div>
Toggling based on class matching is one of the harder thing to do in JQuery, however to achieve what you require you could do the following:
/* When a btn is clicked */
$('.btn').click(function(e) {
/* Extract the classes of this button element */
const classes = $(this).attr('class');
/* Parse the project class part of the classes string */
const projectClass = classes.match(/project\d+/)[0];
/* Construct a matcher for the projects corresponding
content and "toggle" the content's visiblity */
$('.content.' + projectClass).toggle();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="project1 btn">BTN 1</div>
<div class="project2 btn">BTN 2</div>
<div class="project3 btn">BTN 3</div>
<div class="project4 btn">BTN 4</div>
<div class="project1 content">CONTENT 1</div>
<div class="project2 content">CONTENT 2</div>
<div class="project3 content">CONTENT 3</div>
<div class="project4 content">CONTENT 4</div>
You can try to use regex to the class started with "project" and then show or hide it
$('.btn').click(function (e) {
var classArray = $(this).attr("class"),
re = /^project[0-9]+/ ,
className = re.exec(classArray)[0];
$('.content.'+ className).toggle();
});
$('.btn').click(function (e) {
var classArray = $(this).attr("class"),
re = /^project[0-9]+/ ,
className = re.exec(classArray)[0];
$('.content.'+ className).toggle();
});
.content {
display: none
}
.btn {
cursor:pointer
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="project1 btn">BTN 1</div>
<div class="project2 btn">BTN 2</div>
<div class="project3 btn">BTN 3</div>
<div class="project4 btn">BTN 4</div>
<div class="project1 content">CONTENT 1</div>
<div class="project2 content">CONTENT 2</div>
<div class="project3 content">CONTENT 3</div>
<div class="project4 content">CONTENT 4</div>

Scrollable tbody issue

: )
I know this question has been asked a lot, but I tried many solutions and just couldn't make it work properly.
I need to make the tbody of my table scrollable with fixed headers.
To start my table is built dynamically and is very large. 19 columns and about 800 rows.
First I worked with the jquery datatables plugin.
After the table is in the container:
var tbl = createFilter('readDataTbl', '', condition);
$('#tableDiv').empty().append(tbl);
$('#readDataTbl').dataTable({
"scrollY": "200px",
"scrollCollapse": true,
"paging": false
});
but that creates a scroll in x and the headers are frozen like that:
Then I tried a css solution as follows:
<style>
table {
border-collapse: collapse;
width: 100%;
}
thead {
text-align:left;
display: table;
float: left;
width: 100%;
}
thead tr {
display: table-row;
width: 100%;
}
tbody {
display: block;
height: 120px;
overflow: auto;
float: left;
width: 100%;
}
tbody tr {
display: table;
width: 100%;
}
tbody tr {
height: 18px;
}
tbody td {
padding:1px 8px;
}
th, td {
width: 25%;
}
tr:after{ /* IE8 fix */
content: ".";
margin-left: -3px; /* to hide the content above tr */ /* not necessary if you are ok with 1px gap */
visibility: hidden;
}
</style>
But that just creates a mess in the tbody like that:
Then I tried thie method from Here
adjusting the THs width after:
css:
<style>
thead, tbody { display: block; }
tbody {
height: 100px; /* Just for the demo */
overflow-y: auto; /* Trigger vertical scroll */
overflow-x: hidden; /* Hide the horizontal scroll */
}
</style>
js:
var tbl = createFilter('readDataTbl', '', condition);
$('#tableDiv').empty().append(tbl);
var $table = $('table');
var $bodyCells = $table.find('tbody tr:first').children();
// Get the tbody columns width array
var colWidth = $bodyCells.map(function () {
return $(this).width();
}).get();
// Set the width of thead columns
$table.find('thead tr').children().each(function (i, v) {
$(v).width(colWidth[i]);
});
And then I noticed the THs long text made them bigger like that:
what could help me achieve my goal?
Thought about inserting divs inside THs but not sure about it..
Thanks! : ]
You can't do this perfectly without some javascript. The best way to accomplish this would be to use a clone of the header, prepend it to the element, apply a fixed position on it and hide the original. Hope this helps. You might also need to bind each column width to the width of the original.
I think you can use bootstrap css and some table styles. You can adjust the th height and width for better results. Also you must calculate the percentage width of tbody td, thead th { ie if you have 19 columns then 100/19 which is around 5%. So your column width will be very less and you will need to increase the height for thead th {
table {
width: 100%;
}
thead,
tbody,
tr,
td,
th {
display: block;
}
tr:after {
content: ' ';
display: block;
visibility: hidden;
clear: both;
}
thead th {
height: 50px;
/*text-align: left;*/
}
tbody {
height: 120px;
overflow-y: auto;
}
thead {
/* fallback */
}
tbody td,
thead th {
width: 19.2%;
float: left;
}
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<table class="table table-striped">
<thead>
<tr>
<th>Make fg jfdg jfgj fgjfg jfgj fgj fgj g jfgj fgj dfgj fgjfg</th>
<th>Model</th>
<th>Color</th>
<th>Year</th>
</tr>
</thead>
<tbody>
<tr>
<td class="filterable-cell">Fordfghdfg jfdgjfdgj fgj fdgj fgjfgj df</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
</tbody>
</table>
You can do this with the help of flex-box layout. It certainly won't work on safari though. All other major browsers render it perfectly.
/* CSS */
html, body {
height: 100%;
width: 100%;
overflow: hidden;
margin: 0;
padding: 0;
}
.table {
height: 100%;
width: 100%;
}
.table .tr {
display: flex;
flex-flow: row wrap;
}
.table .tr .td, .table .tr .th {
flex: 1;
}
.table .thead {
padding-right: 17px;
/* this padding accounts for the width of the scroll bar
* you could compute the default scrollbar width for any browser and set this padding accordingly
* else the headers and records will be misaligned by that margin. */
}
.table .viewport {
height: 640px;
overflow: scroll;
}
/* HTML */
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="ftable.css" />
<title>Flex tables</title>
</head>
<body>
<div class="table">
<div class="thead">
<div class="tr">
<div class="th">Column 1</div>
<div class="th">Column 2</div>
<div class="th">Column 3</div>
<div class="th">Column 4</div>
<div class="th">Column 5</div>
</div>
</div>
<div class="viewport tbody">
<div class="canvas">
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
<div class="tr">
<div class="td">Value 1</div>
<div class="td">Value 2</div>
<div class="td">Value 3</div>
<div class="td">Value 4</div>
<div class="td">Value 5</div>
</div>
</div>
</div>
</div>
</body>
</html>

Wrap around groups of elements using jQuery

I've got a list of elements and I want to group them with div starting with the class HEADER and end it if the class is BREAK or the last element.
So the code below,
<div class="test">Test 0</div>
<div class="header">Header 1</div>
<div class="test">Test 1</div>
<div class="header">Header 2</div>
<div class="test">Test 2</div>
<div class="test">Test 3</div>
<div class="break">Break 1</div>
<div class="header">Header 3</div>
<div class="test">Test 4</div>
<div class="test">Test 5</div>
<div class="header">Header 4</div>
<div class="test">Test 6</div>
<div class="break">Break 2</div>
<div class="test">Test 7</div>
<div class="header">Header 5</div>
<div class="test">Test 8</div>
Would become,
<div>
<div class="test">Test 0</div>
<div class="group">
<div class="header">Header 1</div>
<div class="test">Test 1</div>
<div class="header">Header 2</div>
<div class="test">Test 2</div>
<div class="test">Test 3</div>
</div>
<div class="break">Break 1</div>
<div class="group">
<div class="header">Header 3</div>
<div class="test">Test 4</div>
<div class="test">Test 5</div>
<div class="header">Header 4</div>
<div class="test">Test 6</div>
</div>
<div class="break">Break 2</div>
<div class="test">Test 7</div>
<div class="group">
<div class="header">Header 5</div>
<div class="test">Test 8</div>
</div>
<div>
Any ideas? Thanks in advance.
You can use wrapAll() method as shown below:
$(".header").each(function() {
var $group = $(this).nextUntil(".break").addBack();
if (!$(this).closest(".group").length)
$group.wrapAll('<div class="group"/>');
});
.group {
background: dodgerblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">Test 0</div>
<div class="header">Header 1</div>
<div class="test">Test 1</div>
<div class="header">Header 2</div>
<div class="test">Test 2</div>
<div class="test">Test 3</div>
<div class="break">Break 1</div>
<div class="header">Header 3</div>
<div class="test">Test 4</div>
<div class="test">Test 5</div>
<div class="header">Header 4</div>
<div class="test">Test 6</div>
<div class="break">Break 2</div>
<div class="test">Test 7</div>
<div class="header">Header 5</div>
<div class="test">Test 8</div>
Reference:
each()
addBack()
nextUntil()
closest()

Categories