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/
Related
I am trying to re-write some jquery so that uses a selector I had previously created, so that it doesn't need to access the DOM again. The selector I had created already access the DOM once, and I want to use its contents in a string literal in a function.
My current code is the following:
$(this.$content[$(`.nav a[href$="${window.location.hash}"]`).parent().index()]).show();
which works just fine, but ".nav a" is accessing the DOM, which I do not want in this instance. I want to use this.$navigation, which I had created before and already has the information from the DOM. I tried writing it as
$(this.$content[$(`this.$navigation.find('a')[href$="${window.location.hash}"]`).parent().index()]).show();
where this.navigation = $("#main-nav"), the parent of the .nav elements, but it does not work in this way.
Any suggestions on how I might approach this?
The inner jQuery object should be moved outside of the string literal, and the attribute selector needs to be placed inside the find() call.
$(this.$content[$(this.$navigation).find(`a[href$="${window.location.hash}"]`).parent().index()]).show();
In addition, I would assume from the naming convention that $navigation already holds a jQuery object so does not need to be wrapped again. As such, this should work:
$(this.$content[this.$navigation.find(`a[href$="${window.location.hash}"]`).parent().index()]).show();
I'm creating a JQuery object(let's call it $dummyHTML) and setting some html content inside it. Then I go through each of it's child nodes including text ones, do some checks, and append them to a new different JQuery Object(let's call it $refinedHTML).
But the problem is that the contents of $dummyHTML seems to be empty even before I append them to $refinedHTML!
Now, I know that JQuery append function doesn't copy a node, it actually transfers the node to the other JQuery object. So I'm guessing the append function triggers before I mean it to?
Here is a minified example of the issue.
var $dummyHTML = $('<div/>');
$dummyHTML.html('Hello there, <span>myself!</span>');
var $refinedHTML = $('<div/>');
console.log($dummyHTML[0]);
$dummyHTML.contents().each(function() {
$refinedHTML.append($(this));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
But if I remove the .contents part the programs works as expected.
.contents() extracts the content of a DOM element .When you create an object on the fly,it is not yet a DOM element so .contents() will not work however you can manipulate the object data in other ways.
Reference here:
Given a jQuery object that represents a set of DOM elements, the .contents() method allows us to search through the immediate children of these elements in the DOM tree and construct a new jQuery object from the matching elements.
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');
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
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.