codek
codek

Reputation: 343

How can I dynamically wrap elements in a div within another div?

I have the following output of WordPress content:

<a href="#">link1</a>
text1
<br>
<br>
<a href="#">link2</a>
text2
<br>
<br>
<a href="#">link3</a>
text
<br>
<br>
<a href="#">link4</a>
text4
<br>
<br>

I DO NOT have access to edit the content so I'm looking to edit this via jQuery. I need to wrap each link with the text and br before next link in a div and then split it in two columns. So the final result would be something like this:

<div class="col-left">
    <div class="item">
        <a href="#">link1</a>
        text1
        <br>
        <br>
    </div>
    <div class="item">
        <a href="#">link2</a>
        text2
        <br>
        <br>
    </div>
</div>
<div class="col-right">
    <div class="item">
        <a href="#">link3</a>
        text3
        <br>
        <br>
    </div>
    <div class="item">
        <a href="#">link4</a>
        text4
        <br>
        <br>
    </div>
</div>

Any idea how can I achieve this using jQuery?

I have tried using .wrap() like this:

$('a').wrap( "<div class='item'></div>" );

Upvotes: 1

Views: 1912

Answers (3)

bowheart
bowheart

Reputation: 4676

This is the closest I could get. It gives the desired outcome, but I'm not sure that it's terribly flexible.

var textNodes = $('a').first().parent().contents().filter(function() {
    return this.nodeType === 3 && $(this).text() !== "\n";
});
$(textNodes).each(function() {
    $(this).wrap('<span></span>');
});

var groups = $('a');
$(groups).each(function(index, item) {
    $(item).before('<div class="item"></div>');
    var theDiv = $(item).prev();
    var theItem = $(item).detach();
    var theRest = theDiv.nextUntil('a').detach();
    theDiv.append(theItem);
    theDiv.append(theRest);
    theDiv.find('span').contents().unwrap();
});

var theDivs = $('.item');
var half = theDivs.length / 2;

$(theDivs).first().before('<div class="col-left"></div><div class="col-right"></div>');
var i;
for (i = 0; i < half; i++)
{
    var nextDiv = $(theDivs[i]).detach();
    $('.col-left').append(nextDiv);
}
for (; i < theDivs.length; i++)
{
    var nextDiv = $(theDivs[i]).detach();
    $('.col-right').append(nextDiv);
}

And here's the JSFiddle. Cheers.

Upvotes: 0

Dave Salomon
Dave Salomon

Reputation: 3297

That's a pretty fun challenge.

A quick explanation...
jQuery appears to struggle when getting text elements which aren't wrapped in any tag, so we must fist wrap them. I've used a <span>. I've used the code from this post to do that.

Now that they're all wrapped up nicely, we can select the elements we're interested in, and find the halfway point. If we have an odd number, let's call Math.ceil, so that the extra one ends up in the Left column.

var a = $('a');
var i = Math.ceil(a.length/2);

Now let's just get the first column and second column elements by calling $.slice.

var firstColEls = a.slice(0,i);
var secondColEls = a.slice(i);

We can now loop through the elements and add the <div> with the item class. I'm using itemC1 and itemC2 so we can quickly select all the grouped elements later on. The class can have the same styling.

$.each(firstColEls, function(idx,el){
    $(el).nextUntil('a').addBack().wrapAll('<div class="itemC1"></div>');
});
$.each(secondColEls, function(idx,el){
    $(el).nextUntil('a').addBack().wrapAll('<div class="itemC2"></div>');
});

Now let's select the items, and wrap all of them (together) in the left/right column divs!

$('.itemC1').wrapAll('<div class="l"></div>');
$('.itemC2').wrapAll('<div class="r"></div>';



Wasn't that fun? :). Working Fiddle.

Upvotes: 2

dhershman
dhershman

Reputation: 341

Have you tried setting a variable like so:

if (check how many links) {
var wrapLinkLeft = $('<div class="col-left"><div class="item"><a href="#">link1<br><br></a></div></div>');
var wrapLinkRight = $('<div class="col-right"><div class="item"><a href="#">link2<br><br></a></div></div>');

 $(wrapLinkLeft).appendTo('body'); //for example append it to the body
 }

to make the link dynamic leave it empty and just append it to the href, which means you will probably need to set a class or ID for this href or build a counter to keep track of where the scripts at.

Upvotes: 0

Related Questions