Don't lose variable data when removing element - javascript

How can I save elements to variable, then remove it, but not lose the variable data?
var elements = $('.element');
elements.remove();
elements.insertAfter('.insertAfterElement');

Use .detach() instead of .remove().
From docs:
The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.

From http://api.jquery.com/remove/:
In addition to the elements themselves, all bound events and jQuery
data associated with the elements are removed. To remove the elements
without removing data and events, use .detach() instead.
From http://api.jquery.com/detach/:
The .detach() method is the same as .remove(), except that
.detach() keeps all jQuery data associated with the removed
elements. This method is useful when removed elements are to be
reinserted into the DOM at a later time.
But of course, if you are going to insert it back to the document immediately, there is no point in using that.
$('button').on('click', function() {
$('.element').insertAfter('.insertAfterElement');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Wrapper <span class="element">Element</span></div>
<button>Click me</button>
<div class="insertAfterElement"></div>

From http://api.jquery.com/remove/:
To remove the elements without removing data and events, use .detach() instead.
So you'd use
var elements = $('.element');
elements.detach();
// later:
elements.insertAfter('.insertAfterElement');
However, if you only want to move the elements around immediately, you don't need to explicitly remove them from the DOM at all. Just inserting them in a different position will implicitly remove them from their old position (instead of getting them cloned). So simply use
$('.element').insertAfter('.insertAfterElement');

Related

If I bind a JavaScript event to an element, then delete the element, what happens to the event?

Let's say I have an element:
<section id="container">
<div id="curious">hey, there</div>
</section>
Then, after the DOM loads, I bind an event to the element, like so:
$('#curious').click(function (){
alert('Are you curious?');
});
Later on, the element gets deleted:
$('#container').html('');
What happens to the bound event? Is it deleted too? Does it linger around? Is it a good practice to clean it up?
According to the jQuery documentation for the .html() method, the event handlers are removed.
This is done to prevent memory leaks.
When .html() is used to set an element's content, any content that was in that element is completely replaced by the new content. Additionally, jQuery removes other constructs such as data and event handlers from child elements before replacing those elements with the new content.
Similarly, the same applies when using the .empty()/.remove() methods as well:
all bound events and jQuery data associated with the elements are removed.
If you want to retain the data and event listeners, use the .detach() method instead. The .detach() method is essentially the same as the .remove() method except for the fact that it keeps all jQuery data associated with the removed elements (which means that you can append the same element after detaching it, and the events would still be bound).

appending element and removing it destroys all event handlers in jquery?

Ok I create element, assign click handler, and append it to body. Then i remove it and reappend it and click handler is no longer working???
Why would this happen.
var btn = $('<button>').text('hi').click(function(){console.log(3);});
var div = $('<div>');
div.append(btn);
$('body').append(div);
//click it now, it works..
div.html('');
div.append(btn);
// now button doesn't work..
So why is this happening and what can i do to fix it.
Since .html('') is essentially the same as .empty(), the following applies (from the jQuery docs):
To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.
If you want to remove elements without destroying their data or event handlers (so they can be re-added later), use .detach() instead.
One option would be to use event delegation. In doing so, the event isn't bound directly to the button element, it is bound to a constant parent element that isn't removed.
Example Here
$(document).on('click', 'button', function () {
// ..
});
As mentioned above, another option would be to use the .detach() method in order to remove the element from the DOM, without removing attached event listeners.
The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.
Example Here
div.find('button').detach();
div.append(btn);
put this after the second div.append(btn); - > btn = $('button').text('hi').click(function(){console.log(3);});
This is very interesting situation. What happens when you clear div with html('') method. Take a look at source code and you will see that internally jQuery calls jQuery.cleanData(getAll(elem, false));. This method is responsible for removing all the related data for all child elements that have already been removed. This is important in order to avoid memory leaks.
Clearing data also removes events bound with on (and similar) methods, because those event handlers are also stored in internal cache object.
So as the result, even though you removed content of the div, the btn object is still in memory, but the event bound to it previously is gone.
This was the explanation of the problem. The solution is to use dedicated method called detach. It will remove button from the DOM but will keep event data in case element will later be appended again.
// remove element but keep its data
btn.detach();
// append back
div.append(btn);
In situations like this you should not use html('').
It happens because you're calling html() on the DIV that contains the button.
When you call html() with an empty string, it calls empty() internally.
Calling empty() on an element iterates over all the elements inside that element removing all data and events securely.
It does this by calling jQuery.cleanData on the button, which again explicitly calls jQuery.removeEvent, removing all events on the button.
The button is still stored in the variable btn, so it can be appended again, but it has lost all data and any events attached to it because the parent element had html("") called on it.
The solution is to use detach() to remove the element with all the data and events intact, so it can be appended again, or you can attach the event to a parent element that isn't removed, or you could just hide the element, generally there's no reason to remove the element just to reappend it, it's better to hide it.
FIDDLE

jQuery: Add Sibling of Parent to Current Matched Elements

I'm trying to - in one line - remove the parent element of a clicked element and the parent's lone sibling element. This is my two-liner solution here:
$(document).ready(function() {
$('.close').click(function() {
$(this).parent().siblings('.sibling').remove();
$(this).parent().remove();
});
});
Here's a working fiddle. I'm looking to avoid navigating the DOM twice since I've already found the parent of the clicked element when I remove the sibling, there's no reason I should be doing it again. I'm aware that I could wrap both the parent and sibling in an element and just remove that super element, but at this point I'd like to avoid that as well.
I've looked into using jQuery's .add() function, but I can't seem to get that to work. Thanks for your help!
You're looking for .addBack():
$(this).parent().siblings('.sibling').addBack().remove();
Demo
andSelf is an equivalent to .addBack() for jQuery < 1.8
With .add(), you would have to store the parent in a variable to avoid traversing to it twice:
var $father = $(this).parent();
$father.siblings('.sibling').add($father).remove();
//one-liner without storing in a variable would traverse the DOM twice:
$(this).parent().siblings('.sibling').add($(this).parent()).remove();
As you can see, the addBack method is more practical in this case.
In case the element's parent and the parent's sibling are the only elements inside their parent, you can also use:
$(this.parentNode.parentNode).empty();
Demo
The native parentNode property is a bit faster than jQuery's .parent() method. It is up to which to use.
Note that such small traversing has very little overhead either way. Your original code and these versions have very little difference performance-wise.

jquery remove() and detach() method [duplicate]

This question already has an answer here:
Difference between remove() and detach() in jQuery [closed]
(1 answer)
Closed 10 years ago.
I m not being able to distinguish between the jquery remove() and detach() method as both are acting same or working same ,plz consider the code:
<script>
$(document).ready(function(){
$("#btn1").click(function(){
$("body").append($("#p1").detach());
});
$("#btn2").click(function(){
$("body").append($("#p2").remove());
});
$("p").click(function(){
$(this).animate({fontSize:"+=1px"})
});
});
</script>
From the docs:
The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.
remove() destroys the element completely. detach() removes the element, keeping its data intact.
The detach method doesn't remove interal jQuery data that are associated with the elements (e.g. event bindings), so it's only if there is any such data that you would see any difference.
To move an element from one place to another in the document, you don't have to remove it or detach it, just append it in the new place:
$("body").append($("#p1"));
You're not going to see a visible difference between the two. This excerpt is taken from the jQuery documentation:
The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.
Please review the API documentation on each of these calls:
jQuery Remove
jQuery Detach
As explained by the documentation, $.detach() retains the associated jQuery data whereas $.remove() removes that data. This data contains things like the bound events, the animation queue and whatever you manually added with $.data().
In your original example, you should be able to notice the difference in the following scenario:
Click the paragraph.
Click the button.
Click the paragraph again.
For #p1 and #btn1, clicking the paragraph the second time will still trigger the click handler and bump the font size. This is because the event handler is stored in the data and is retained by detach(). Thus, when reattaching it to the DOM, the handler is still bound.
For #p2 and #btn2 however, the event handler is removed by remove() and clicking on the paragraph the second time won't do anything.
Side note: you don't need to call detach() when you're immediately appending it to the DOM again. detach() may be interesting if you want to store the element in a variable for a while until it needs to be re-appended (with the same data and behaviour). remove() is commonly used to just destroy an element, also cleaning up any associated data.

Where does jQuery data's method information go?

Can I do
<div class="some_div">some div</div>
<script>
jQuery('.some_div').data('some_data','some info').remove();
</script>
where the information is added with data's method, is still around the DOM? Do I need to uninitialize? Is the information automatically removed when the div element has no references left?
The data is stored in a variable available to the jQuery objects via closure. It is never stored in the dom. Remove method deletes the data along with the DOM element.
.remove( [ selector ] )
Similar to .empty(), the .remove()
method takes elements out of the DOM.
We use .remove() when we want to
remove the element itself, as well as
everything inside it. In addition to
the elements themselves, all bound
events and jQuery data associated with
the elements are removed.
source: jQuery API: remove()
jQuery places a serial number on DOM elements when needed, and uses that reference to look up associated data for the element.
For example: jQuery1278101043588: 1
As long as the element exists, your data should exist. No references to the element in code are needed.
The data associated with an element is cleaned up when you call .remove() or .empty().
If you wish to remove an element from the DOM without losing the data, you can use .detach().
http://api.jquery.com/remove/
http://api.jquery.com/empty/
http://api.jquery.com/detach/
jQuery also has a .removeData() method for clearing data that is no longer needed. It will clear all data on the element(s) if called without passing an argument.
http://api.jquery.com/removeData/

Categories

Resources