开发者

Use JQuery to wrap multiple sets of elements in a Div

I'm working on a dropdown menu and need to mutate the existing html markup with JQuery to make it fit the design.

Here is a simplified example: Wrap all "ul's" that contain more than one "li" in a div (in the 开发者_C百科same div, NOT one div for each UL).

<ul>
    <li>foo</li>
</ul>
<ul>
    <li>foo</li>
    <li>foo</li>
</ul>
<ul>
    <li>foo</li>
    <li>foo</li>
</ul>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

<script>
my_selection = [];
i = 0;
// find all ul's that have more than one li
$("ul").each(function(){
    if($(this).find("li").length > 1){
        // add this to my_selection
        my_selection[i] = $(this);
        i++;
    } // if
}); // each

// wrap my_selection in div tags
$(my_selection).wrapAll(document.createElement("div"));
</script>

The above code gives this firebug error:

"Node cannot be inserted at the specified point in the hierarchy" code: "3"

How can I make it work?


This would be a much cleaner approach:

$('ul:has(li)').wrap('<div></div>');

First, you don't need to create the node, just provide the wrapping string to jQuery. Second, use the :has selector in this instance to cut down on the each functionality in your example. Finally, (this will depend on your intended functionality) you may want to use wrap instead of wrapAll.

EDIT: Another option would be to approach it from the other way around. Get the <li> tags then grab the <ul> parent:

$('li:not(:only-child)').parent().filter('ul').wrap('<div></div>');


This is a bit of a hack.

<script>
jQuery( function() {
    my_selection = [];

    i = 0;
    n = 0;
    jQuery( 'ul' ).each( function() {
        var ul = jQuery( this );
        if ( ul.children().length > 1 ) {
            my_selection[n++] = 'ul:eq(' + i + ')';
        }
        ++i;
    } );

    jQuery( my_selection.join( ',' ) ).wrapAll( document.createElement( 'div' ) );
} );
</script>


I'm not sure if jQuery can take arrays as selectors. In $(my_selection), my_selection is not a jQuery object but an array of objects. You can try generating jQuery objects in the first place, using var my_selection = $(''); ... my_selection.add($(this));.

Also, with .wrapAll() method, you can just use: .wrapAll('<div></div>');.


You have a bug in your code, attempting to wrap your LI's by DIV.

<script>
my_selection = [];
i = 0;
// find all ul's that have more than one li
$("ul").each(function() {
    var $ul = $(this);
    if ($ul.find("li").length > 1){
        // add this to my_selection
        my_selection[i] = $ul;
        i++;
    } // if
});

// wrap my_selection in div tags
$(my_selection).wrap(document.createElement("div"));
</script>


I was a bit busy when I answered this question, sorry for all the problems. This following solves the problem correctly.

<script type="text/javascript">
jQuery( function() {
    jQuery( 'ul' ).find( 'li:eq(1)' ).parent().wrapAll( '<div></div>' );
} );
</script>

Edit: I changed li:gt(0) to li:eq(1), they both work, but one makes more sense.

It's simple, it goes through all the ul's and their children, it tries to grab the 2nd child. If the 2nd child is found it then goes back to it's parent to add it to the wrapAll method.

Edit: It looks like if you edit your post more than 8 times times it becomes a Community Wiki, interesting.


These are all great answers. But I notice that your script is not inside a $(document).ready(function(){...}) and you seemed to verify this error still exists with other code that wasn't wrapped in the ready function.

I tried and found that William's code worked (+1 to him), but because of my OCD I cleaned it up a bit

$(document).ready(function(){
 my_selection = [];
 $('ul').each(function(i){
  if ($(this).find('li').length > 1 ){
   my_selection.push(['ul:eq(' + i + ')']);
  }
 });
 $( my_selection.join(',')).wrapAll('<div class="wrapper"></div>');
})
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜