jQuery grouping adjacent elements

My content management system allows users to easily insert blocks of content onto a page. These blocks can be of different types and inserted in any order. A sample high-level DOM structure may appear like this:

<p>Some rich text</p>

<div class="box">...</div>
<div class="box">...</div>
<div class="box">...</div>

<h3>Some more rich text</h3>
<p>Lorem ipsum</p>

<div class="box">...</div>
<div class="box">...</div>

I am looking to group any adjacent 'box' divs within a wrapping 'container' div. In the given example, two 'container' divs would need to be added as there are two sets of box divs, resulting in:

<p>Some rich text</p>

<div class="container">
    <div class="box">...</div>
    <div class="box">...</div>
    <div class="box">...</div>
</div>

<h3>Some more rich text</h3>
<p>Lorem ipsum</p>

<div class="container">
    <div class="box">...</div>
    <div class="box">...</div>
</div>

I don't believe this can be achieved with CSS selectors, so I'm curious if anyone knows how to accomplish this using jQuery.

Answer №1

Utilize the following jQuery methods:

  1. .nextUntil - to retrieve all the subsequent .box elements.
  2. .andSelf - to include the current element in the collection.
  3. .wrapAll - to enclose each collection within a separate .container.

$('.box').not('.box+.box').each(function(){
  $(this).nextUntil(':not(.box)').addBack().wrapAll('<div class="container" />');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Some rich text</p>

<div class="box">...</div>
<div class="box">...</div>
<div class="box">...</div>

<h3>Some more rich text</h3>
<p>Lorem ipsum</p>

<div class="box">...</div>
<div class="box">...</div>

http://jsbin.com/gonino/edit?html,js

Answer №2

One possible approach is to achieve this by following the example provided in this JSFiddle demo that I quickly put together.

The idea is to iterate through each element with the class .box, store them in an array, and check if the next element also belongs to the .box class:

var collection = [];
$('.box').each(function() {
    var nextBox = $(this).next().hasClass('box');
    ...
    collection.push($(this));
})

In case the next element does not have the class .box, it creates a parent container, inserts it before the first .box within the collection array, and then moves all the .box elements into this container using appendTo:

if(!nextBox)
{
    var container = $('<div class="collection"></div>');
    container.insertBefore(collection[0]);
    for(i=0;i<collection.length;i++)
    {
        collection[i].appendTo(container);
    }
    collection = [];
}

Answer №3

Check out the fiddle right over here: http://jsfiddle.net/jdelight/XutA6/5/ I've come up with a cool solution using CSS that allows you to style blocks with a single background color and border. Here's how the HTML would look:

    <div class="block">this is block 1</div>
    <div class="block">this is block 2</div>
    <div class="block">this is block 3</div>
    <div class="block">this is block 4</div>
    <div class="block">this is block 5</div>

Now, let's take a look at the CSS:

            /* This styles all blocks with the necessary background color and border */
        .block {
            background: #eee;
            color: #000;
            border: 1px solid red;
            border-bottom: 0;
            padding: 20px;
            width: 400px;
            border-radius: 20px;
            /* Eliminate rounded corners from bottom left/right */
            border-bottom-left-radius:0;
            border-bottom-right-radius:0;
            position: relative;
        }
        /* Style all adjacent blocks while removing the radius - giving the top block a radius and the rest none */
        .block + .block {
            border-radius: 0;
            border-top: 0;
        }

        /* Hidden "cheeky" block with content below all other blocks */
        /* The bottom property ensures it is only visible under the very bottom block (see bottom: -10px) */
        /* Styling for rounded corners on this particular block */
        .block::after {
            content:'.';
            display: block;
            background: red;
            height: 10px;
            position: absolute;
            border-bottom: 1px solid red;
            border-left:  1px solid red;
            border-right:  1px solid red;
            bottom: -10px;
            width: 440px;
            background: #eee;
            left:-1px;
            border-bottom-left-radius:10px;
            border-bottom-right-radius:10px;
        }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The menu positioned beneath the logo is malfunctioning

Upon downloading a template from the internet, I created a menu at the top with the logo positioned below it. However, when scrolling down, the menu items were supposed to turn black with a white background, resembling this: https://i.sstatic.net/1HTLZ.jp ...

Can someone assist me with accessing jQuery variables within the agiletoolkit (ATK4) framework?

I am trying to retrieve the window height and width of the browser using ATK4, a PHP framework integrated with jQuery The JavaScript code for this would be $(window).height(); $(window).width(); Since agiletoolkit works with jQuery, I believe it shou ...

Tips for securing a navbar in material ui

https://i.stack.imgur.com/CYfmQ.png In my current React project, I am facing an issue with aligning components within the Material-UI AppBar Component. My aim is to achieve a seamless and perfectly straight alignment for three key elements: a logo image, ...

When clicked on, Bootstrap creates a stylish border of blue lines around the designated

Hey there, I've noticed a strange issue that only seems to occur in Google Chrome on both desktop and mobile devices. To better illustrate the problem, I have attached a picture. A blue line unexpectedly appears when I interact with certain sections ...

Transform vertical and horizontal scrolling actions into solely horizontal scrolling using HTML and JS

I'm currently working on a unique React.js website that features a horizontal-scrolling portfolio. The website functions as a visual gallery, allowing users to easily scroll through images using their trackpad. Within the website, I have set up a lar ...

What is the best way to choose every single element on the webpage excluding a specific element along with all of its children?

Is there a way to hide all content on a page except for a specific element and its children using CSS? I've been exploring the :not selector, but I'm struggling to make it work with the * selector. :not(.list-app) { display: none; } :not(. ...

Boost your Youtube page load speed with Greasemonkey and jQuery techniques

Have you ever noticed how long it can take for a YouTube video page to load on a slow computer? The sidebar, comments, uploader's icon, and other images all contribute to the delay. But fear not, my script is here to save the day. With just a click, y ...

Error: Unable to add dynamic dropdown list to the search field of jqgrid due to undefined variable 'e'

I'm currently attempting to incorporate a dynamic dropdown list into the search field of jqgrid. Here are the details of my code: Within the jsp page: <s:url var="selecturl" action="selectAction"/> <sjg:gridColumn name="lastName" index="l ...

Is there a way to adjust the background hues of a React component when a click event is triggered?

Currently, I have 3 React components that each consist of a div element. When I click on one component, I want to change its background color to black. If I then select another component, the previously selected component should return to its normal back ...

Difficulty adapting CSS using JavaScript

I am looking to adjust the padding of my header to give it a sleeker appearance on the page. I attempted to achieve this with the code below, but it seems to have no effect: function openPage() { var i, el = document.getElementById('headbar' ...

When I click the mouse, my drawing function starts lines from the top left corner instead of the latest point

http://codepen.io/FreelanceDev/pen/kLpJSf?editors=1010 You can find my CodePen project through the provided link. While the HTML and CSS elements are working correctly, I am facing issues with the JavaScript functionality. The desired outcome should be d ...

The speed of jQuery's $.each function is quite lackluster

I am facing a challenge in creating a dynamic combo box using $.each and $('<OPTION>'). The rendering speed is significantly slower on IE (taking 3/4 minutes to display data after receiving the server response) compared to Firefox and other ...

Implementing icon display upon click in a Meteor application

Currently, I am in the process of developing an application using meteor and within one of the templates, I have the following code snippet. <h3> <b> <a class="viewed" href="/jobdetails/{{_id}}">{{title}}</a> </b> ...

Why does the slider only slide once, what could be the reason for

Can someone help me with my slider issue? It runs only once and stops on the 2nd image. I need it to keep sliding every 5 seconds. Check out the source: http://codepen.io/zuraizm/pen/vGDHl Here is the Javascript code: var slideCount = $('#slider ul ...

Trouble with :active CSS selector not functioning when clicking on child element in IE8

I am dealing with the following HTML structure: <div id="ctr__Wrapper" class="wrapper"> <div id="ctr" class="control clickable"> <img src="logo.png"> </div> </div> Here is the CSS code for this setup: .contr ...

Using jQuery to handle click events and unbinding them

I am new to learning jQuery and not a software developer. In the code below, I have added the .green class to the .show_hide div when clicked, and I would like to remove the .green class from the .show_hide div when it is clicked again. Additionally, I w ...

Is there a way for me to choose multiple checkboxes simultaneously?

I have a dynamically created HTML table with checkboxes added for each row. $.each(data, function(id, value) { rows.push('<tr><td><input type="checkbox" autocomplete="off" class="chkbox" name="chkbox" value="'+value.site+' ...

Concealing an element upon clicking with jQuery

Can someone help me with this issue? I'm trying to use jQuery to hide the div element with the ID 'professional-panel' when a button with the ID 'hideButton' is clicked. I know it should be simple, but I'm new to jQuery and s ...

Utilize custom fonts from your local directory within a Vite Vue3 project

Inside my main.scss file, I am loading local fonts from the assets/styles/fonts folder: @font-face { font-family: 'Opensans-Bold'; font-style: normal; src: local('Opensans-Bold'), url(./fonts/OpenSans-Bold.ttf) format('truety ...

What is the best way to display various dialogs based on the specific button that is clicked?

Starting a new project, I foresee the need for numerous dialog boxes and modals. I've come up with some basic code that displays the dialog when a button is clicked and hides it when the cancel button is pressed. However, I'm facing the issue o ...