skip to Main Content

I’m just trying to wrap a div w class of slide around every 3 divs with a class of search-audio.

the one error i’m running into is that it’s saying elem.parentElement is undefined…

So part works great…

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 trouble is here – wrapping a div around the new array of grouped elements.

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 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>

3

Answers


  1. I think you are over complicating it a bit, it could be possible just using CSS for this by using :nth-child to apply the styles of .search-audio to every 3rd div of class .slide.

    This code might be wrong but something like:

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

    Here’s a few links that might be useful to learn how to use them:

    Login or Signup to reply.
  2. The problem is that elem isn’t a single element, it’s an array of 3 elements that was created by groupBlocks(). So there’s no elem.parentElement.

    Use elem[0].parentElement to get the common parent of the all the elements. And then loop over them to append each element to the new div.

    I’ve renamed elem to group in the code below, to more correctly match what it contains.

    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>
    Login or Signup to reply.
  3. First note: classNames can not be a number.

    Here is a snippet that groups the elements in groups of 3 using a reducer and then wraps those groups in a grouping element.

    // create groups 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;
      }, [[]]);
      
    wrap(sliderGroups);
    
    // wrap the groups
    function wrap (array) {
      const sliderGroup = Object.assign(
        document.createElement(`div`), {className: `slideGroup`});
      const sliderCollection = document.querySelector(`.slider`);
      array.forEach( elemGroup => {
        // create a new wrap Node
        const wrap = sliderGroup.cloneNode();
        // append it to div.slider
        sliderCollection.append(wrap);
        // append *moves* the (life) elements of
        // the current group to the wrap element
        wrap.append(...elemGroup);
      });
    }
    .search-audio:after {
      content: "search-audio elem";
      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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search