Jan Krakora
Jan Krakora

Reputation: 2610

jQuery wrap and appendTo doesn't lead in expected result

I'm trying to wrap some HTML content inside a div container and then append a span to that container. But I can't figure out why the appended span doesn't appear.

So I'm curious if I'm doing something wrong.

$('button').click(function() {
	
    var $container = $('<div class="container"></div>');
	$('.target').wrap($container);
			
    $label = $('<span class="duration-label">Hi there</span>');
	$label.appendTo($container);
});
.target {
    border: 1px solid black;
}

.container {
    background: red;
    padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>

<div class="target">
    <span>This is some unimportant text</span>
</div>
<button type="button">Click me</button>

Upvotes: 3

Views: 52

Answers (3)

Amit
Amit

Reputation: 46361

The reason is that the .wrap() method wraps each element in the set of matched elements with a new element structure - copies of $container.

$container itself is not the wrapping element, it's just a "template" for wrapping elements, so you need to grab the actual element(s) if you want to further manipulate them.

This of course is simple to understand once you consider the fact that after the call there can be more then 1 such element.

$('button').click(function() {

  var $container = $('<div class="container"></div>');
  var $wrappingContainer = $('.target').wrap($container).parent();

  // sanity check:
  if($container[0] == $wrappingContainer[0]) {
    alert('Same object?!?!'); // Should not happen
  }

  $label = $('<span class="duration-label">Hi there</span>');
  $label.appendTo($wrappingContainer);
});
.target {
  border: 1px solid black;
}
.container {
  background: red;
  padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>

<div class="target">
  <span>This is some unimportant text</span>
</div>
<button type="button">Click me</button>

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1075825

It's because wrap makes a copy of the wrapper you give it, it doesn't use the one you give it directly. You're appending to the one you gave it.

Instead, use the one you wrapped around the content:

$('button').click(function() {

  // Wrap .target with the div, and get a reference to
  // the newly-created wrapper
  var $container =
          $('.target')
              .wrap('<div class="container"></div>')
              .parent();

  // Add a label to it
  var $label = $('<span class="duration-label">Hi there</span>');
  $label.appendTo($container);
});
.target {
  border: 1px solid black;
}
.container {
  background: red;
  padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>

<div class="target">
  <span>This is some unimportant text</span>
</div>
<button type="button">Click me</button>


Side note: Your code was falling prey to The Horror of Implicit Globals because you didn't declare $label. It's important to declare your variables. You can use strict mode to have the JavaScript engine keep you from creating globals implicitly.

Upvotes: 2

Milind Anantwar
Milind Anantwar

Reputation: 82241

That is because $container refers to variable and not object of wrapped element. You need to get the object or use relevant selector to append to container element :

$label.appendTo('.container');

Working Demo

Upvotes: 1

Related Questions