iglvzx
iglvzx

Reputation: 508

Wrapping elements with the same attribute

If I have a list of similar elements, such that:

<outer-container>
    <element attribute="x" />
    <element attribute="x" />
    .
    .
    .
    <element attribute="y" />
    <element attribute="z" />
</outer-container>

How can I wrap the elements with attribute="x" so they are within their own container?

<outer-container>
    <inner-container>
        <element attribute="x" />
        <element attribute="x" />
    </inner-container>
    .
    .
    .
</outer-container>

Upvotes: 0

Views: 196

Answers (2)

cliffs of insanity
cliffs of insanity

Reputation: 3694

I changed your HTML to make it easier to test.

<div>
    <input attribute="x" />
    <input attribute="x" />
    <p>divider</p>
    <input attribute="y" />
    <input attribute="z" />
</div>

Assuming you want all of the elements of that kind in one container, positioned where the first one was found, you can do this.

   // invoked like this
wrapAll('input[attribute=x]', 'span');

   // implemented like this
function wrapAll(selector, wrapper) {
    if (typeof wrapper === 'string')
        wrapper = document.createElement(wrapper);
    else if (!wrapper || !wrapper.nodeType)
        throw "Illegal 'wrapper' argument."

    var els = document.querySelectorAll(selector);

    els[0].parentNode.insertBefore(wrapper, els[0]);

    for(var i = 0, len = els.length; i < len; i++)
        wrapper.appendChild(els[i]);
}

http://jsfiddle.net/5z2uA/4/


If you wanted different consecutive groups to be wrapped together, you can do this.

   // invoked like this
wrapAdjacent('input[attribute=x]', 'span');

   // implemented like this
function wrapAdjacent(selector, wrapper) {
    if (typeof wrapper === 'string')
        wrapper = document.createElement(wrapper);
    else if (!wrapper || !wrapper.nodeType)
        throw "Illegal 'wrapper' argument."

    var els = document.querySelectorAll(selector);

    for (var i = 0, len = els.length; i < len; ) {
        var this_wrapper = wrapper.cloneNode(false);
        els[i].parentNode.insertBefore(this_wrapper, els[i]);
        do {
            this_wrapper.appendChild(els[i]);
            i++;
        }
        while (nextEl(this_wrapper) === els[i])       
    }
}
function nextEl(el) {
    while (el && (el = el.nextSibling) && el.nodeType !== 1) {}
    return el;
}

http://jsfiddle.net/5z2uA/5/

Upvotes: 1

iambriansreed
iambriansreed

Reputation: 22271

If jQuery is an option:

$('[attribute="x"]').wrapAll('<inner-container/>');

Demo: http://jsfiddle.net/iambriansreed/Hgp7B/

Upvotes: 2

Related Questions