'Javascript how to wrap elements in groups

I have this DOM:

<div class="section">Section</div>
<div>Text</div>
<div>Image</div>
<div>Text</div>
<div>Gallery</div>
<div class="section">Section</div>
<div>Text</div>
<div>Image</div>
<div>Text</div>
<div>Gallery</div>

but I want to a wrap the elements like this:

<div class="relative">
    <div class="section">Section</div>
    <div>Text</div>
    <div>Image</div>
    <div>Text</div>
    <div>Gallery</div>
</div>
<div class="relative">
    <div class="section">Section</div>
    <div>Text</div>
    <div>Image</div>
    <div>Text</div>
    <div>Gallery</div>
</div>

So I tried this:

function getSiblings(elm, withTextNodes) {
  if (!elm || !elm.parentNode) return

  let siblings = [
     ...elm.parentNode[withTextNodes ? 'childNodes' : 'children'],
   ],
  idx = siblings.indexOf(elm)

  siblings.before = siblings.slice(0, idx)
  siblings.after = siblings.slice(idx + 1)

  return siblings
}

const sections = document.querySelectorAll('.section')

sections.forEach((section) => {
  const elmSiblings = this.getSiblings(section)

  // children elements to be wrapped inside the wrapper
  const children = elmSiblings.before

  const wrapper = document.createElement('div')
  wrapper.classList.add('section-wrapper')

  section.parentNode.insertBefore(wrapper, section)
  wrapper.appendChild(section)
})

but this only wraps the ´section´ element inside the newly created section-wrapper

how can I achieve this?



Solution 1:[1]

Something like this, testing the nextElementSibling

document.querySelectorAll(".section").forEach(sec => {
  let next = sec.nextElementSibling; // important to get this before wrapping
  const wrapper = document.createElement("div")
  wrapper.classList.add("relative")
  sec.insertAdjacentElement("beforeBegin", wrapper)
  wrapper.append(sec);
  while (next && !next.classList.contains("section")) {
    const nextSib = next.nextElementSibling; // important to get this before appending
    wrapper.append(next)
    if (nextSib) next = nextSib;
    else next = null
  }
})
.relative {
  background-color: red
}

.section {
  background-color: yellow
}
<div class="section">Section1</div>
<div>Text 1</div>
<div>Image 1</div>
<div>Text 2</div>
<div>Gallery 1</div>
<div class="section">Section2</div>
<div>Text 2.1 </div>
<div>Image 2</div>
<div>Text 2.2</div>
<div>Gallery 2</div>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1