javascriptjquerywrapall

.wrapAll() based on adjacent siblings' class and


I have a series of DIVs that are assigned .big or .small based on size. They need to be wrapped in groups of two or three. Practically speaking, only two .bigs can fit in the allotted space.

If two .big DIVs exist adjacent to one another, they should be wrapped in groups of two. Otherwise, the DIVs should be wrapped in groups of three.

Please let me know what I've done wrong and how to make it work. Below is an example with comments on where the wraps should break. Below that is what I've tried in jQuery, and a link to jsFiddle.

<div class="big post">big</div>
<div class="big post">big</div>
    <!-- should be wrap break -->
<div class="big post">big</div>
<div class="big post">big</div>
    <!-- should be wrap break -->
<div class="big post">big</div>
<div class="small post">small</div>
<div class="big post">big</div>
    <!-- should be wrap break -->
<div class="small post">small</div>
<div class="small post">small</div>
<div class="big post">big</div>
    <!-- should be wrap break -->
<div class="big post">big</div>
<div class="small post">small</div>
    <!-- should be wrap break -->

I think the if, below, works pretty well, but the else breaks all the things.

$('.post').each(function() {    
    if ( $(this).hasClass('big') && $(this).next('.post').hasClass('big') ) {    
        var allElements = $(this).next().andSelf(),
            WRAP_BY = 2;
        for (var i = 0; i < allElements.length; i += WRAP_BY) {
            allElements.slice(i, i + WRAP_BY).andSelf().wrapAll('<div class="flowed" />');
        }//for                            
    }//if
else {
    // the else breaks all the things
        var allElements = $(this).next().andSelf(),
            WRAP_BY = 3;
        for (var i = 0; i < allElements.length; i += WRAP_BY) {
            allElements.slice(i, i + WRAP_BY).andSelf().wrapAll('<div class="flowed" />');
        }//for                                        
}//else
});//each

http://jsfiddle.net/natejones/UvsZE/


Solution

  • first - you need to return from function, if elements, already wrapped,

    second, i not understand why you need for loop in else(you can use $.nextAll() to get all sibling after current)

    here the code

    $('.post').each(function() {
        //return if already wrapped!
        if ($(this).parent().hasClass('flowed')) {
            return;
        }
        var WRAP_BY = 3;
        if ($(this).hasClass('big') && $(this).next('.post').hasClass('big')) {
            WRAP_BY = 2;
        }
        var allElements = $(this).nextAll().andSelf();
        allElements.slice(0, WRAP_BY).wrapAll('<div class="flowed" />');
    }); //each​