I have created a DOM fragment where I am adding several childNodes in a loop:
fragment.appendChild( clone )
I want to take this fragment and use it to replace an existing HTML element that already contain those nodes.
I can use
myContainer.appendChild(fragment)
However this is done also in a loop and the fragment is appended too many times.
How can I get the fragment, append it to myContainer and delete also myContainer's old childs.
Thank you.
You probably want:
while (myContainer.childNodes.length > 0) {
myContainer.removeChild(myContainer.childNodes[0]);
}
myContainer.appendChild(fragment);
Can you not append the Fragment after the loop has finished?
As for removing the current child nodes, you could cycle through them all and use the removeChild function, or you could just set the innerHTML of the element to an empty string. If you reset the innerHTML before you append the fragment it should be fine.
myContainer.innerHTML = "";
myContainer.appendChild(fragment);
If I understand you correctly, you are creating a new node with some children, and you want this new node to replace an existing node in your page.
You can either:
Remove all children of the existing node, and add the new children to the existing node
Add all the children to another node (I think that is what you are doing: adding to the fragment), then remove the existing node, and add the node to that place.
See removeChild and appendChild
Related
I have heard few approaches:
I could simply iterate through 20k elements and do appendChild.
I could insert All items into newly created div in js and then just put that div into parent dom.
Is there any other approach? Copy html wholesale?
However, I am confused on how to do 2. What is the best way to move all child element from div A to div B without iterating over all of them.
You can also use document fragment which appends all at one moment
var fragment = document.createDocumentFragment();
fragment.appendChild(...)
fragment.appendChild(...)
...
element.appendChild(fragment)
According to this source the fastest is to simply iterate through the elements and append them.
Far better than creating a random div is to create a document fragment and append to that fragment. Then, said fragment can be added to the dom
var fragment = document.createDocumentFragment()
arr.forEach(el => fragment.appendChild(el))
element.appendChild(fragment)
I made a jsPerf that contains an experiment about which of these two are faster. It appears that using document fragment is the same as raw append with my limited test (one browser, one OS)
Why not just using cloneNode() in deep mode:
// Copy the element and its child nodes
var cln = itm.cloneNode(true);
// Append the cloned element to the new div with id="new_div"
document.getElementById("new_div").innerHTML(cln);
Hope this helps.
I have a jquery element. and I remove it from DOM by using remove(), but jQuery still keep a reference of it.
and later I still can use it and insert it into DOM.
How to detect that this "var p" is in DOM or off DOM ?
var p=$('p');
p.remove();
console.log(p);
p.insertAfter($('body'));
I think p.parent() is more easy way to go. if it in DOM it will get another DOM node
use javascript length to check if dom element exists or not
if($("p").length>0)
{
// p exists
}
var p=$('p');
p.remove();
So when you did p.remove(), it is removed from the dom but it still exists in memory as a stand alone dom node object with all its contents intact.
You can perform any operation as in normal dom element like append anywhere, change contents or change attributes.
The only difference is that it is not part of the document unless you append it in the html.
jQuery has contains method to check if the element is part of the document
jQuery.contains(document, $foo[0]));
p.parent() in case of removed p will return a 0 length jquery object because p is independent node and has no parent.
I'm playing around with a document fragment. I find it hard to understand how it behave when I append it to the DOM.
I create a doc fragment that I assign to a variable, when I insert some stuff into it, and append the doc fragment into a element. But if I clear the element my variable which should reference to the doc fragment contain an empty document fragment.
I trying to make a cache for a third party lib that creates document fragments. So I would like to get this working. Should I create a cloneNode before I append the fragment to the DOM, is that correct?
I have created a JS fiddle:
http://jsfiddle.net/4CTXG/1/
var test = document.createDocumentFragment();
//var test = document.createElement("div"); // This one work
$(test).append($("<div>").html('Hello world!'));
$("#result").append(test);
setTimeout(function(){
$("#result").children().remove();
$("#result").append(test);
console.log('Now test should have been appended');
$(result).css({"background": "#FF0000"});
},5000)
When you append an Element (e.g. the <div>) into the DOM, the Element gets added as a child of its new parent. The div's children are not changed. When you remove the element from its parent, the Element is just detached from the DOM. It you still have a reference to the Element it will still contain its children, available to reattach later.
When you append an DocumentFragment into the DOM, the children of the DocumentFragment are removed from the DocumentFragment and moved to be children of its DOM element parent. The DocumentFragment is now empty.
So instead of appending the DocumentFragment, you should append a deep clone of the fragment.
See http://dom.spec.whatwg.org/#concept-node-insert for the gory details.
Javascript objects are copied by reference rather than value. So when you assign the fragment to a variable and then insert the fragment into the DOM, both the variable and the DOM are referencing the same object. Any change you make to one will also occur in the other.
If you really want the variable to reference an object that is distinct from the DOM, then cloning is the right approach.
I've always wondered how this jQuery feature works: $('<span>Hello world</span>')[0]
That is supposed to return a reference to the newly created span element. How can I achieve the same result using the native DOM methods? insertAdjacentHTML? innerHTML? documentFragment?
I need to insert a HTML fragment and hold a reference to the outer element without the need of using createElement/appendChild.
Thanks.
It's possible to create an element, set its innerHTML, and return the first child. The container element is never added to the DOM:
var el = document.createElement('div');
el.innerHTML = '<span>Hello world</span>';
console.log(el.firstChild);
If that's wrapped in a function, I believe the original container will be eligible for garbage collection as soon as the child is appended somewhere else.
jQuery seems to be doing something more sophisticated, checking if the string contains a single tag or not, and creating a fragment for more complicated strings. See the parseHTML method on jQuery's source code.
So when the code ...
document.getElementById('classhere').childNodes
... runs, I manage to get all elements with that ID EXCEPT for elements that have been dynamically created by a 'createDiv()' function:
function createDiv()
{
var divTag = document.createElement("div");
divTag.id = "classhere" + num;
...
I would like to get all div elements with that Id, even dynamically created div elements. Does anyone have a solution? Thanks!
Try out jQuery
jQuery Wildcard Selector
http://www.emadibrahim.com/2009/07/25/jquery-wildcard-selector/
So when the code ...
document.getElementById('classhere').childNodes
... runs, I manage to get all elements with that ID
getElementById looks up a single element by ID, not by class. That line as quoted will look up an element with the id value "classhere" and return a NodeList of its immediate child nodes (elements, text nodes, etc.). If you create further elements and either don't add them to the DOM, or add them elsewhere (not as immediate children of the "classhere" element), they won't be on the NodeList. It has nothing to do with whether they were created during the main HTML parsing or after-the-fact with JavaScript.
I would like to get all div elements with that Id...
There can be only one element with a given ID.
If you're trying to find all elements whose id starts with "classname", you can use an "attribute starts with selector":
var divs = $("div[id^='classname']");
...gives you a jQuery object containing all of the matching divs as of the time you executed the statement (unlike a NodeList, it's not live; if you change things you'll have to run the selector again).