COS
COS

Reputation: 553

jQuery wrap each class + class elements ( different classes )

I'm trying to wrap each two elements close to each other containing the classes black and blue in a <div class="wrap"> across my page.

I tried this, but it doesn't work as I need:

$(".black, .blue").each(function() {
  $(this).next().hasClass('black').wrapAll('<div class="wrap"></div>')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col red"></div>
<div class="col black"></div>
<div class="col blue"></div>
<div class="col red"></div>
<div class="col white"></div>
<div class="col yellow"></div>
<div class="col red"></div>
<div class="col black"></div>
<div class="col bllue"></div>

This is my desired output:

<div class="col red"></div>

<div class="wrap">
    <div class="col black"></div>
    <div class="col blue"></div>
</div>

<div class="col red"></div>
<div class="col white"></div>
<div class="col yellow"></div>
<div class="col red"></div>

<div class="wrap">
    <div class="col black"></div>
    <div class="col blue"></div>
</div>

Upvotes: 1

Views: 134

Answers (2)

Rory McCrossan
Rory McCrossan

Reputation: 337560

Your current approach is flawed as you loop over both the .black and .blue elements, only try to detect following .black elements, and also because you use hasClass(), which returns a boolean value, yet try to then call a method on it.

To achieve this you can loop over every .black and determine if the next() element is .blue. If it is you can wrap them both in a div, like this:

$('.black').each(function() {
  var $this = $(this);
  var $next = $this.next();
  if ($next.is('.blue'))
    $this.add($next).wrapAll('<div class="wrap"></div>');
});
.red { color: red; }
.black { color: black; }
.blue { color: blue; }
.white { color: white; }
.yellow { color: yellow; }

.wrap { 
  border: 1px dotted #CCC;
  background-color: #EEE;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col red">Foo</div>
<div class="col black">Foo</div>
<div class="col blue">Foo</div>
<div class="col red">Foo</div>
<div class="col white">Foo</div>
<div class="col yellow">Foo</div>
<div class="col red">Foo</div>
<div class="col black">Foo</div>
<div class="col blue">Foo</div>

Using your example I would like to add a third element having the same class blue.

I assume in this scenario that there may be an unlimited number of .blue elements after the .black, and they should all be wrapped. In that case use nextUntil() along with :not(.blue), like this:

$('.black').each(function() {
  var $this = $(this);
  if ($this.next().is('.blue')) {
    $this.add($this.nextUntil(':not(.blue)')).wrapAll('<div class="wrap"></div>');
  }
});
.red { color: red; }
.black { color: black; }
.blue { color: blue; }
.white { color: white; }
.yellow { color: yellow; }

.wrap { 
  border: 1px dotted #CCC;
  background-color: #EEE;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col red">Foo</div>
<div class="col black">Foo</div>
<div class="col blue">Foo</div>
<div class="col red">Foo</div>
<div class="col white">Foo</div>
<div class="col yellow">Foo</div>
<div class="col red">Foo</div>
<div class="col black">Foo</div>
<div class="col blue">Foo</div>
<div class="col blue">Foo</div>
<div class="col blue">Foo</div>
<div class="col red">Foo</div>

Upvotes: 2

User863
User863

Reputation: 20039

Use + Next Adjacent Selector (“prev + next”)

$(".black + .blue").each(function() {
  $(this).prev().addBack().wrapAll('<div class="wrap"></div>')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col red"></div>
<div class="col black"></div>
<div class="col blue"></div>
<div class="col red"></div>
<div class="col white"></div>
<div class="col yellow"></div>
<div class="col red"></div>
<div class="col black"></div>
<div class="col blue"></div>

Upvotes: 2

Related Questions