问题描述:

This is my first post on stackoverflow. So far I could always find an answer here, but this time I couldn't.

Here is my DOM structure:

<div id="elementA">

<div id="elementB"></div>

<div id="elementC">

<div id="elementD"></div>

</div>

<div id="elementE"></div>

</div>

How can I wrap 2 or more selected "random" elements into a wrapper container? This should also work if the selected elements are on different level and if there are other elements in between. UPDATE: The DOM structure of all other elements shouldn't be effected.

Following a few examples:


Example 1:

I though of something like this:

var element1 = $('#elementB');

var element2 = $('#elementE');

??? $(element1, element2).myWrap(".wrapper"); ???

Result should look like this:

<div id="elementA">

<div class="wrapper">

<div id="elementB"></div>

<div id="elementC">

<div id="elementD"></div>

</div>

<div id="elementE"></div>

</div>

</div>


2 Example:

Elements are in different levels.

var element1 = $('#elementD');

var element2 = $('#elementE');

??? $(element1, element2).myWrap(".wrapper"); ???

Result:

<div id="elementA">

<div id="elementB"></div>

<div class="wrapper">

<div id="elementC">

<div id="elementD"></div>

</div>

<div id="elementE"></div>

</div>

</div>


Example 3: More than 2 elements:

var element1 = $('#elementD');

var element2 = $('#elementC');

var element3 = $('#elementA');

??? $(element1, element2, element3).myWrap(".wrapper"); ???

<div class="wrapper">

<div id="elementA">

<div id="elementB"></div>

<div id="elementC">

<div id="elementD"></div>

</div>

<div id="elementE"></div>

</div>

</div>


Example 4: Different trees:

var element1 = $('#elementD');

var element2 = $('#elementF');

??? $(element1, element2).myWrap(".wrapper"); ???

<div id="elementA">

<div id="elementB"></div>

<div class="wrapper">

<div id="elementC">

<div id="elementD"></div>

</div>

<div id="elementE">

<div id="elementF"></div>

</div>

</div>

</div>

Thanks for you help in advance.

网友答案:

As was pointed out in the comments above, the first example is different to the others in that when the specified children are all direct decendants, then all children in the common parent should be wrapped.

Using this logic, the following solution works.

jQuery.fn.myWrap = function(options) {
    var e = this;

    // find most nested
    var max = null;
    var $mostNested = null;

    $(e).each(function(i, elem) {
        var parents = $(elem).parents().length;
        if (parents > max || max == null) {
            max = parents;
            $mostNested = $(elem);
        }
    })

    // find common parent
    var found = false;
    $parent = $mostNested.parent();
    while($parent != null && !found) {
        if ($parent.find(e).length == e.length) {
            // Right Level
            found = true;
            var toWrap = [];
            var numDirect = 0;
            $.each($parent.children(), function(i, item) {
                var direct = $(e).index(item) >= 0;
                var sibling = $(item).find(e).length > 0;
                if (direct) numDirect++;
                if (direct || sibling) toWrap.push(item);
            })
            if (numDirect == e.length) {
                // All direct! (Example 1)
                $parent.children().wrapAll("<div class='wrapper'></div>");
            } else {
                // Other Examples
                $(toWrap).wrapAll("<div class='wrapper'></div>");
            }
        }
        $parent = $parent.parent();    
    }
};


$(document).ready(function() {
    // Example 1
    $('#elementB, #elementE').myWrap();
    // Example 2
    //$('#elementD, #elementE').myWrap();
    // Example 3
    //$('#elementD, #elementC, #elementA').myWrap();
    // Example 4
    //$('#elementD, #elementF').myWrap();
})

See my fiddle.

相关阅读:
Top