Перенос элементов с одинаковым классом рядом друг с другом в обычном Javascript

#javascript

#javascript

Вопрос:

Ищу способ обертывания элементов рядом друг с другом с одинаковым классом в оболочке. Это можно легко сделать в jquery, но я изо всех сил пытаюсь найти способ в чистом JS. Я смог удалить пустые теги между .group, но не уверен, как обернуть эти элементы.

http://jsfiddle.net/chille1987/6cnjgft0/4/

Текущий HTML

 <div class="group">1</div>
<div class="group">2</div>
<p><br /></p>
<div class="group">3</div>

<p>Lorem ipsum dolor sit amet</p>

<section>
    <div class="group">4</div>
    <div class="group">5</div>
</section>

<p>Lorem ipsum dolor sit amet</p>

<div class="group">6</div>
 

Ожидаемый HTML

 <div class="wrapper">
    <div class="group">1</div>
    <div class="group">2</div> 
    <div class="group">3</div>
</div>

<p>Lorem ipsum dolor sit amet</p>

<section>
    <div class="wrapper">
        <div class="group">4</div>
        <div class="group">5</div>
    </div>
</section>    

<p>Lorem ipsum dolor sit amet</p>

<div class="wrapper">
    <div class="group">6</div>
</div>
 

Javascipt

 // Create Wrapper
let wrapper = document.createElement('div');
wrapper.classList.add('wrapper');

// Add class to br parent
let brTags = document.querySelectorAll('br:first-child');
brTags.forEach(empty => {
    empty.parentNode.classList.add('empty-paragraph');
});

// remove empty paragraphs between groups
const empty = document.querySelectorAll('.empty-paragraph');
empty.forEach(paragraph => {
    if (paragraph.nextElementSibling.classList.contains('group') amp;amp; paragraph.previousElementSibling.classList.contains('group')) {
        paragraph.remove();
    }
});
 

Комментарии:

1. Все вышеперечисленные .group элементы являются братьями и сестрами. Можем ли мы предположить, что это обязательно будет правдой?

2. На самом деле это не так, это не обязательно должны быть братья и сестры. Некоторые элементы .group могут находиться внутри другого элемента (div, section …)

3. Тогда как бы мы их сгруппировали? Каким будет ожидаемый результат <p class="group">x</p><div><p> class="group">y</p></div>... ?

4. Ожидаемый результат будет <div class="wrapper"><p class="group">x</p><div> и <div><div class="wrapper"><p> class="group">y</p></div></div>

5. Хорошо, итак, группируем их в пределах одного и того же родительского элемента, но не все они имеют одного и того же родительского элемента.

Ответ №1:

Я полагаю, что я бы сделал это от родителя к родителю, и я бы удалил «пустые» абзацы за один проход, а затем сгруппировал вещи в другом (вы могли бы сделать все это за один проход, но это сложнее).

Смотрите Комментарии встроенные:

 // A function to handle one parent
function groupChildren(parent) {
    let child;

    // Remove "blank" paragraphs first
    child = parent.firstElementChild;
    while (child) {
        // Grab this first, since we may remove `child`
        const next = child.nextElementSibling;
        if (!child.classList.contains("group")) {
            // "Blank" means it has nothing but BR elements or blank text nodes
            const remove = child.tagName === "P" amp;amp; Array.from(child.childNodes).every(c =>
                (c.nodeType === Node.TEXT_NODE amp;amp; !c.nodeValue) ||
                (c.tagName === "BR")
            );
            if (remove) {
                parent.removeChild(child);
            }
        }
        child = next;
    }

    // Find and group .group paragraphs
    let group;
    child = parent.firstElementChild;
    while (child) {
        const next = child.nextElementSibling;
        if (child.classList.contains("group")) {
            if (!group) {
                // No group yet, create one and insert it
                group = document.createElement("div");
                group.classList.add("wrapper");
                parent.insertBefore(group, child);
            }
            // Move this into the current group
            group.appendChild(child);
        } else {
            // Break the group here
            group = null;
        }
        child = next;
    }
}

// Handle all of the `.group` elements; often later ones will have been
// handled when handling earlier ones in the same parent, so check for that
for (const child of Array.from(document.getElementsByClassName("group"))) {
    if (!child.parentElement.classList.contains("wrapper")) {
        groupChildren(child.parentElement);
    }
} 
 <div class="group">1</div>
<div class="group">2</div>
<p><br /></p>
<div class="group">3</div>

<p>Lorem ipsum dolor sit amet</p>

<section>
    <div class="group">4</div>
    <div class="group">5</div>
</section>

<p>Lorem ipsum dolor sit amet</p>

<div class="group">6</div> 

Комментарии:

1. Работает отлично!!! Спасибо!!! Я изо всех сил пытался заставить это работать.