Alex Davis Alex Davis - 3 months ago 19
HTML Question

How to prepend element into its respective sibling element using jquery

I have a list of

div
s, each containing a
div
with class
item
and a
p
with class
text
. I'm trying to move each
p.text
element into its respective
div
sibling using jQuery. Here's what I tried:



$('.text').prependTo('.item');

<div class="container">
<p class="text">Sample text.</p>
<div class="item">
<p>More text</p>
</div>
</div>

<div class="container">
<p class="text">Sample text.</p>
<div class="item">
<p>More text</p>
</div>
</div>

<div class="container">
<p class="text">Sample text.</p>
<div class="item">
<p>More text</p>
</div>
</div>


<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>





It seems to collect all three
p
elements and and put the three into each
div
, creating nine
p
elements, like this:

<!-- Undesired result -->
<div class="container">
<div class="item"><p class="text">Sample text.</p><p class="text">Sample text.</p><p class="text">Sample text.</p>
<p>More text</p>
</div>
</div>

<div class="container">
<div class="item"><p class="text">Sample text.</p><p class="text">Sample text.</p><p class="text">Sample text.</p>
<p>More text</p>
</div>
</div>

<div class="container">
<div class="item"><p class="text">Sample text.</p><p class="text">Sample text.</p><p class="text">Sample text.</p>
<p>More text</p>
</div>
</div>


Is there a way to use jQuery to just take each
p
element and move it into its respective sibling
div
element, resulting in the following?

<!-- Desired result -->
<div class="container">
<div class="item">
<p class="text">Sample text.</p>
<p>More text</p>
</div>
</div>

<div class="container">
<div class="item">
<p class="text">Sample text.</p>
<p>More text</p>
</div>
</div>

<div class="container">
<div class="item">
<p class="text">Sample text.</p>
<p>More text</p>
</div>
</div>

Answer

It seems to collect all three p elements and and put the three into each div, creating nine p elements.

Yup, that's what that jQuery asks it to do. :-) It says "Find all .text elements, and prepend them all to all .item elements, making clones as necessary." From the prependTo documentation:

If there is more than one target element, however, cloned copies of the inserted element will be created for each target except the last.

This is the case with all of those sorts of jQuery methods.

Instead, you want a loop:

$('.text').each(function() {
  var elm = $(this);
  elm.prependTo(elm.nextAll('.item').first());
});

or if you know it'll really be the next sibling:

$('.text').each(function() {
  var elm = $(this);
  elm.prependTo(elm.next());
});

Example (I've added a border to the .item elements so you can see the text moves into them):

setTimeout(function() {
  $("#legend").text("AFTER");
  $('.text').each(function() {
    var elm = $(this);
    elm.prependTo(elm.nextAll('.item').first());
  });
}, 600);
.item {
  border: 1px solid black;
}
<div id="legend">BEFORE</div>
<div class="container">
  <p class="text">Sample text.</p>
  <div class="item">
    <p>More text</p>
  </div>
</div>

<div class="container">
  <p class="text">Sample text.</p>
  <div class="item">
    <p>More text</p>
  </div>
</div>

<div class="container">
  <p class="text">Sample text.</p>
  <div class="item">
    <p>More text</p>
  </div>
</div>
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>

Comments