encasing a container element around every trio of elements

I'm currently working on grouping every 3 divs with a class of search-audio inside a div with a class of slide.

The issue I'm facing is that it's giving me an error stating that elem.parentElement is undefined...

However, the initial part of the code is functioning correctly...

const audioBlocks = document.querySelectorAll('.search-audio');
const slider = document.querySelector('.slider');
const audioBlockArr = Array.from(audioBlocks);

function groupBlocks(arr, len) {

    let groups = [],
        i = 0,
        n = arr.length;
  
    while (i < n) {
      groups.push(arr.slice(i, i += len));
    }
  
    return groups;
}

newArr = [...groupBlocks(audioBlockArr, 3)];

The main challenge lies in wrapping a div around the newly grouped elements array.

let wrap = (array) => {
  
  array.forEach((elem) => {
    let div = document.createElement('div');
    div.classList.add('slide');
    div.innerHTML = '';

    elem.parentElement.insertBefore(div, elem);
    div.appendChild(elem);
  });
}

wrap(newArr);

Full code:

const audioBlocks = document.querySelectorAll('.search-audio');
const slider = document.querySelector('.slider');
const audioBlockArr = Array.from(audioBlocks);

function groupBlocks(arr, len) {

  let groups = [],
    i = 0,
    n = arr.length;

  while (i < n) {
    groups.push(arr.slice(i, i += len));
  }

  return groups;
}

newArr = [...groupBlocks(audioBlockArr, 3)];

let wrap = (array) => {
  array.forEach((elem) => {
    let div = document.createElement('div');
    div.classList.add('slide');
    div.innerHTML = '';

    elem.parentElement.insertBefore(div, elem);
    div.appendChild(elem);
  });
}

wrap(newArr);
body {
  font-family: system-ui;
  background: #f06d06;
  color: white;
  text-align: center;
}

.search-audio {
  height: 12rem;
  width: 12rem;
  background: rgb(255, 153, 0);
  margin: .5rem;
  display: inline-block;
}

.slide {
  background-color: #555;
}
<body>
  <div class="slider">
    <div class="search-audio 1"></div>
    <div class="search-audio 2"></div>
    <div class="search-audio 3"></div>
    <div class="search-audio 4"></div>
    <div class="search-audio 5"></div>
    <div class="search-audio 6"></div>
    <div class="search-audio 7"></div>
    <div class="search-audio 8"></div>
    <div class="search-audio 9"></div>
    <div class="search-audio 10"></div>
    <.....
    ......
    ></div>
</body>

</html>

Answer №1

The issue arises from elem not being a single element, but rather an array of 3 elements generated by the groupBlocks() function. This means that there is no direct elem.parentElement.

To address this, utilize elem[0].parentElement to access the common parent of all elements in the array. Then iterate over each element to append them to the new div.

In order to make the code more descriptive of its contents, I have renamed elem to group below.

const audioBlocks = document.querySelectorAll('.search-audio');
const slider = document.querySelector('.slider');
const audioBlockArr = Array.from(audioBlocks);

function groupBlocks(arr, len) {

  let groups = [],
    i = 0,
    n = arr.length;

  while (i < n) {
    groups.push(arr.slice(i, i += len));
  }

  return groups;
}

newArr = [...groupBlocks(audioBlockArr, 3)];

let wrap = (array) => {
  array.forEach((group) => {
    let div = document.createElement('div');
    div.classList.add('slide');
    div.innerHTML = '';

    group[0].parentElement.insertBefore(div, group[0]);
    group.forEach(elem => div.appendChild(elem));
  });
}

wrap(newArr);
body {
  font-family: system-ui;
  background: #f06d06;
  color: white;
  text-align: center;
}

.search-audio {
  height: 12rem;
  width: 12rem;
  background: rgb(255, 153, 0);
  margin: .5rem;
  display: inline-block;
}

.slide {
  background-color: #555;
}
<body>
  <div class="slider">
    <div class="search-audio 1"></div>
    <div class="search-audio 2"></div>
    <div class="search-audio 3"></div>
    <div class="search-audio 4"></div>
    <div class="search-audio 5"></div>
    <div class="search-audio 6"></div>
    <div class="search-audio 7"></div>
    <div class="search-audio 8"></div>
    <div class="search-audio 9"></div>
    <div class="search-audio 10"></div>
    <div class="search-audio 11"></div>
    <div class="search-audio 12"></div>
    <div class="search-audio 13"></div>
    <div class="search-audio 14"></div>
    <div class="search-audio 15"></div>
    <div class="search-audio 16"></div>
    <div class="search-audio 17"></div>
    <div class="search-audio 18"></div>
    <div class="search-audio 19"></div>
    <div class="search-audio 20"></div>
  </div>
</body>

</html>

Answer №2

It seems like you might be overthinking it a bit. With just CSS, you could simplify the process by using the :nth-child selector to apply the styles of .search-audio to every 3rd div with the class of .slide.

While the code below may need some adjustments, the concept is something along these lines:

.slide:nth-child(3n) {
  /* insert styles from .search-audo here */
}

If you're interested in learning more about this technique, check out these resources:

Answer №3

Please take note that classNames cannot be a number (class="search-audio 1).

Check out this code snippet, which groups elements in sets of 3 using a reducer and then wraps those sets in a grouping element:

// grouping elements in sets of 3
const sliderGroups = [...document.querySelectorAll(`.search-audio`)]
  .reduce((acc, el, i) => {
    if (i && i%3 == 0) {
      acc = [...acc, []];
    }
    acc[acc.length - 1] = acc[acc.length - 1].concat(el);
    return acc;
  }, [[]]);
// now you have an array of arrays 
// containing 3 elements each. Let's wrap
// them up
wrap(sliderGroups);

function wrap (array) {
  // base wrapper Node
  const wrapperElem = Object.assign(
    document.createElement(`div`), {className: `slideGroup`});
  const sliderCollection = document.querySelector(`.slider`);
  array.forEach( elemGroup => {
    // create a new wrapper Node based on the base one
    const wrap = wrapperElem.cloneNode();
    // append it to div.slider
    sliderCollection.append(wrap);
    // append *transfers* the individual elements of
    // the current group to the wrapping element
    wrap.append(...elemGroup);
  });
}
.search-audio:after {
  content: "search-audio element";
  color: red;
  margin-left: 6px;
}

.slideGroup:before {
  content: "slide group";
  color: green;
}
<div class="slider">
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio]"></div>
    <div class="search-audio]"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
    <div class="search-audio"></div>
</div>

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

Is there a way to transform a string into a human-readable slug?

Is there a way to convert a slugified string into a more human-readable format? I am extracting parameters from a URL: bookmark/10/disco%20asdasd From this, I have the name "disco%20asdasd". However, this is not easily readable so I need to change it to ...

Adjusting the OrbitControl target in a React environment

I attempted to create a model using react-three-fiber and react-drei, but the OrbitControl target setting is causing it to appear too high. import React, { useRef, useState, Suspense, useEffect } from 'react' import { Canvas, useFrame, useLoader, ...

angularjs routing based on conditions

Is there a way to pass a hidden value or optional parameter that is not part of the URL in order to switch between states based on that parameter? I attempted something like this: <a ui-sref="state2({key:'value', optional: 'B'})"> ...

Running PHP scripts from JavaScript

Currently working on a PHP project that involves a dropdown select button in a webpage. The goal is to call a JavaScript function whenever the value of the dropdown changes, and then pass this selected value to retrieve additional details from a MySQL da ...

Troubleshooting 'Warning: Prop `id` did not match` in react-select

Having an issue with a web app built using ReactJs and NextJs. I implemented the react-select component in a functional component, but now I'm getting this warning in the console: Warning: Prop id did not match. Server: "react-select-7 ...

How to pass variables in AngularJS

When displaying data in a grid, I need to change the button icon on click of the active or inactive button. The functionality is working well, but I am having trouble finding the clicked active button to change its icon. In jQuery, we can use "this", but ...

Tips on integrating googleapis with apps script

My goal: I am trying to implement the Google Calendar's API acl.list() in a Google Script using the UrlFetchApp.fetch() function. Issue: The Google script itself has an OAuth token when it runs. However, the problem arises when the UrlFetchApp.fetc ...

What is the best way to activate Cropper once a file has been selected, without encountering a 404 error on the image?

I've been trying to integrate an image cropper into my website, but I'm encountering some issues that I can't seem to resolve. Expected outcome : Upon selecting a picture from the disk using the file input, a modal should appear prompting t ...

width of the cells within the grid table

What is the best way to ensure the width alignment of cells in both the header and main section? I have highlighted the correct option in the image with green checkmarks. Check out the image here. Here is my example and solution: View the code on CodePen. ...

React is throwing an error message stating that setCount is not a valid function

Getting an error saying setCount is not a function. I am new to this, please help. import React, { memo, useState } from "react"; export const Container = memo(function Container() { const { count, setCount } = useState(0); return ( ...

Expanding Global Object Attributes

As a new JS developer, I've been struggling with a common issue related to the Google Maps API. Despite spending countless hours on StackOverflow, I still can't figure it out. In my code, I use the Google Maps API and I'm trying to assign I ...

Storing Ember.js Views for Faster Loading

Exploring the features of AngularJS and Ember, I am curious to know if Ember has the capability to cache views instead of just loading/reloading them. For instance, if I have tabs with templates like "abc.html," "def.html," and "ghi.html," can I create div ...

Mastering the Art of Trimming with Jquery

function DisplayDataForEdit(id) { $("#editContainer").slideDown("medium"); var parentId ='item'+ id; var colIndex = 0; var $row = $("#" + parentId).parent().parent(); $row.find('td').each(f ...

Authenticate users using JavaScript usernames

Below is my registration link that opens a modal: <a href="#registermodal" data-toggle="modal">Register Here</a> Here is the code for the modal dialog: <div class="modal fade" id="registermodal" role="dialog" style="overflow: scroll;"> ...

Version 10.0 of sails is having trouble with an undefined 'schema' when using mysql

i'm currently experimenting with sails js version 0.10.0 using the sails-mysql adapter 0.10.6 I have set up two models: Customer.js module.exports = { connection: 'someMysqlServer', attributes: { name: { type: 'string& ...

Unable to activate Vue 13 keyCode in a text field using jQuery with Laravel Dusk Testing

I've been grappling with this issue for a few days now. I'm trying to create a Laravel Dusk test that incorporates the Vue.js framework. There's a method that should be triggered when the user hits the ENTER key. I recently discovered that ...

Getting json data through ajax in asp.net

I am facing an issue with the variable data in the function ShowFavorites as it is showing as undefined even though my ajax call is returning a json string. <script type="text/javascript"> $(document).ready(function () { ShowFavorites(); fu ...

Discover the world of Google Chrome Apps with the power of chrome.storage.local

While building an application, I encountered a perplexing issue that I need help with: The task involves reading a JSON file and storing its content in localStorage using chrome.storage.local in a Chrome app. Here is a snippet from the JSON file: { "s ...

Utilizing slug URLs effectively in Next.js

In my current project with Next.js, I am working on implementing "dynamic routes". The goal is to update the URL structure such that upon clicking, the URL should look like "myurl.com/article/55". To achieve this, I have utilized the following "link tag": ...

Exploring the navigation options within React Native's DrawerLayoutAndroid component

My goal is to seamlessly navigate between different views using the Drawer layout. It would be ideal if I could achieve this directly in the navBar without having to create a separate toolbar for each view https://i.sstatic.net/joOeB.png Currently, clicki ...