Say I have the following DOM structure and scripts
var test = document.getElementById('test');
test.parentNode.innerHTML += 'hello';
console.log(test.parentNode); // null
console.log(document.getElementById('test').parentNode); // normal result
<div>
<div id="test"></div>
</div>
As above script says, the first outputs null while the second outputs the actual node, does anyone know why the first output null rather than the normal node?
After resetting innerHTML property, browser parses the set contents and creates new elements. The test variable doesn't refer to the new element which also has test id. The original test element is detached from the DOM and has no parent element. test and document.getElementById('test') refer to different DOM Element objects.
Use the createTextNode and appendChild methods instead and see the difference:
var test = document.getElementById('test');
test.parentNode.appendChild(document.createTextNode('hello'));
console.log(test.parentNode);
val += b is actually the same as val = val + b. When written this way, it should be more obvious that you are recreating all elements inside parent.
If you want to append without destroying existing elements, use appendChild and not innerhtml.
Your code in English would say:
Get me a reference to the DOM node with ID 'test'
Now take that DOM node out of the DOM tree and replace it with a new node with the text <div id="test"></div>Hello (not a typo, it will put exactly that string in).
Now show me the parent node of the DOM node you took out of the tree (aha! but it's no longer in the DOM!)
Now get a reference to a DOM node with the ID "test" (it finds the thing that you inserted in step two.
Show me the parent of that node (no problem)
The original DOM node 'test' is still in memory, but no longer in the document. You can see this by looking at test.innerHTML, you will see it still has just the original text, because you're looking at the DOM node in memory.
var test = document.getElementById('test');
test.parentNode.innerHTML += 'additional text';
console.log(test.parentNode); // null
console.log(test.innerHTML);
console.log(document.getElementById('test').parentNode); // normal result
<div>
<div id="test">Original text</div>
</div>
The following line:
test.parentNode.innerHTML += 'hello';
is a shortcut for:
test.parentNode.innerHTML = test.parentNode.innerHTML + 'hello';
This means that test is removed and replaced by the same markup + the string "hello". But your test reference is not in the document anymore.
You can try
test.parentNode.appendChild(document.createTextNode('hello'));
While appending html using test.parentNode.innerHTML += 'hello';(which is equal to test.parentNode.innerHTML = test.parentNode.innerHTML + 'hello';), it's actually recreating the element so, test(which is reference to the element) is no longer available in dom.
Instead create textNode using createTextNode method and append using appendChild method which keep the other elements.
var test = document.getElementById('test');
test.parentNode.appendChild(document.createTextNode('hello'));
console.log(test.parentNode);
console.log(document.getElementById('test').parentNode);
<div>
<div id="test"></div>
</div>
Related
I have an element E and I'm appending some elements to it. All of a sudden, I find out that the next element to append should be the first child of E. What's the trick, how to do it? Method unshift doesn't work because E is an object, not array.
Long way would be to iterate through E's children and to move'em key++, but I'm sure that there is a prettier way.
var eElement; // some E DOM instance
var newFirstElement; //element which should be first in E
eElement.insertBefore(newFirstElement, eElement.firstChild);
2018 version - prepend
parent.prepend(newChild) // [newChild, child1, child2]
This is modern JS! It is more readable than previous options. It is currently available in Chrome, FF, and Opera.
The equivalent for adding to the end is append, replacing the old appendChild
parent.append(newChild) // [child1, child2, newChild]
Advanced usage
You can pass multiple values (or use spread operator ...).
Any string value will be added as a text element.
Examples:
parent.prepend(newChild, "foo") // [newChild, "foo", child1, child2]
const list = ["bar", newChild]
parent.append(...list, "fizz") // [child1, child2, "bar", newChild, "fizz"]
Related DOM methods
Read More - child.before and child.after
Read More - child.replaceWith
Mozilla Documentation
Can I Use
2017 version
You can use
targetElement.insertAdjacentElement('afterbegin', newFirstElement)
From MDN :
The insertAdjacentElement() method inserts a given element node at a given position relative to the element it is invoked upon.
position
A DOMString representing the position relative to the element; must be one of the following strings:
beforebegin: Before the element itself.
afterbegin: Just inside the element, before its first child.
beforeend: Just inside the element, after its last child.
afterend: After the element itself.
element
The element to be inserted into the tree.
In the family of insertAdjacent there is the sibling methods:
element.insertAdjacentHTML('afterbegin','htmlText')`
That can inject html string directly, like innerHTML but without override everything, so you can use it as a mini-template Engin and jump the oppressive process of document.createElement and even build a whole component with string manipulation process
element.insertAdjacentText for inject sanitize string into element . no more encode/decode
You can implement it directly i all your window html elements.
Like this :
HTMLElement.prototype.appendFirst = function(childNode) {
if (this.firstChild) {
this.insertBefore(childNode, this.firstChild);
}
else {
this.appendChild(childNode);
}
};
Accepted answer refactored into a function:
function prependChild(parentEle, newFirstChildEle) {
parentEle.insertBefore(newFirstChildEle, parentEle.firstChild)
}
Unless I have misunderstood:
$("e").prepend("<yourelem>Text</yourelem>");
Or
$("<yourelem>Text</yourelem>").prependTo("e");
Although it sounds like from your description that there is some condition attached, so
if (SomeCondition){
$("e").prepend("<yourelem>Text</yourelem>");
}
else{
$("e").append("<yourelem>Text</yourelem>");
}
I think you're looking for the .prepend function in jQuery. Example code:
$("#E").prepend("<p>Code goes here, yo!</p>");
I created this prototype to prepend elements to parent element.
Node.prototype.prependChild = function (child: Node) {
this.insertBefore(child, this.firstChild);
return this;
};
var newItem = document.createElement("LI"); // Create a <li> node
var textnode = document.createTextNode("Water"); // Create a text node
newItem.appendChild(textnode); // Append the text to <li>
var list = document.getElementById("myList"); // Get the <ul> element to insert a new node
list.insertBefore(newItem, list.childNodes[0]); // Insert <li> before the first child of <ul>
https://www.w3schools.com/jsref/met_node_insertbefore.asp
I have an html element that I'm replacing with a clone of itself to remove event listeners. However, I still want to interact with it after I've replaced it. Unfortunately,
node.replaceWith(node.cloneNode(true))
makes node link to an element that doesn't exist. Is there any way I can get the element that is now where it was? I know I can circumvent this by giving it an id before and querying for it after, but it feels like there should be a better way.
You'll need to store the clone before replacing and then reassign node.
To avoid having the clone hanging around you can wrap the method in a function that returns the clone.
function replaceSelf(node) {
const clone = node.cloneNode(true);
node.replaceWith(clone);
return clone;
}
let node = document.getElementById('to-clone');
node = replaceSelf(node);
node.style.backgroundColor = 'cyan';
<div>
<p id="to-clone">paragraph</p>
</div>
Try replacing this:
node = node.replaceWith(node.cloneNode(true))
with this
node.replaceWith(node.cloneNode(true))
Because replaceWith returns undefined
I have a DOM node, lets say node and this may have some children and has text in it. I need to get only the text from it.
I know that node.innerHTML gives the whole data between the tags but I don't need the child elements. This can be done using jquery once i get the node's id How to get text only from the DIV when it has child elements with text using jQuery? But in that case I am again finding the node which is a waste of time. Right now I already have the node and I only need to get its text. I tried node.text but it is returning undefined value.
Please help.
Looping over the .childNodes and grabbing the .nodeValue of the text nodes should work:
var foo = document.getElementById('foo'),
txt = '';
[].forEach.call(foo.childNodes, function (subNode) {
if (subNode.nodeType === 3) {
txt += subNode.nodeValue;
}
});
console.log(txt);
jsBin
.childNodes is a NodeList, not an array. You cannot use array methods on them, foo.childNodes.forEach() would not work.
NodeList objects are however array-like objects, so we can use Function.prototype.call to treat foo.childNodes as if it were a real array and call Array.prototype.forEach on it.
The callback we provide .forEach checks the .nodeType of each Node, if it is a text node (a Node with a .nodeType of 3) we append it's value to our output buffer.
I am not sure if I understand correctly but if you need the text for each element of the node then for JQuery you would do:
node.each(function (index){
console.debug($(this).text());
});
Here's some sample code:
function addTextNode(){
var newtext = document.createTextNode(" Some text added dynamically. ");
var para = document.getElementById("p1");
para.appendChild(newtext);
$("#p1").append("HI");
}
<div style="border: 1px solid red">
<p id="p1">First line of paragraph.<br /></p>
</div>
What is the difference between append() and appendChild()?
Any real time scenarios?
The main difference is that appendChild is a DOM method and append is a jQuery method. The second one uses the first as you can see on jQuery source code
append: function() {
return this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
this.appendChild( elem );
}
});
},
If you're using jQuery library on your project, you'll be safe always using append when adding elements to the page.
No longer
now append is a method in JavaScript
MDN documentation on append method
Quoting MDN
The ParentNode.append method inserts a set of Node objects or DOMString objects after the last child of the ParentNode. DOMString objects are inserted as equivalent Text nodes.
This is not supported by IE and Edge but supported by Chrome(54+), Firefox(49+) and Opera(39+).
The JavaScript's append is similar to jQuery's append.
You can pass multiple arguments.
var elm = document.getElementById('div1');
elm.append(document.createElement('p'),document.createElement('span'),document.createElement('div'));
console.log(elm.innerHTML);
<div id="div1"></div>
append is a jQuery method to append some content or HTML to an element.
$('#example').append('Some text or HTML');
appendChild is a pure DOM method for adding a child element.
document.getElementById('example').appendChild(newElement);
I know this is an old and answered question and I'm not looking for votes I just want to add an extra little thing that I think might help newcomers.
yes appendChild is a DOM method and append is JQuery method but practically the key difference is that appendChild takes a node as a parameter by that I mean if you want to add an empty paragraph to the DOM you need to create that p element first
var p = document.createElement('p')
then you can add it to the DOM whereas JQuery append creates that node for you and adds it to the DOM right away whether it's a text element or an html element
or a combination!
$('p').append('<span> I have been appended </span>');
appendChild is a DOM vanilla-js function.
append is a jQuery function.
They each have their own quirks.
The JavaScript appendchild method can be use to append an item to another element. The jQuery Append element does the same work but certainly in less number of lines:
Let us take an example to Append an item in a list:
a) With JavaScript
var n= document.createElement("LI"); // Create a <li> node
var tn = document.createTextNode("JavaScript"); // Create a text node
n.appendChild(tn); // Append the text to <li>
document.getElementById("myList").appendChild(n);
b) With jQuery
$("#myList").append("<li>jQuery</li>")
appendChild is a pure javascript method where as append is a jQuery method.
I thought there is some confusion here so I'm going to clarify it.
Both 'append' and 'appendChild' are now native Javascript functions and can be used concurrently.
For example:
let parent_div = document.querySelector('.hobbies');
let list_item = document.createElement('li');
list_item.style.color = 'red';
list_item.innerText = "Javascript added me here"
//running either one of these functions yield same result
const append_element = parent_div.append(list_item);
const append_child_element = parent_div.appendChild(list_item);
However, the key difference is the return value
e.g
console.log(append_element) //returns undefined
whereas,
console.log(append_child_element) // returns 'li' node
Hence, the return value of append_child method can be used to store it in a variable and use it later, whereas, append is use and throw (anonymous) function by nature.
I have an element E and I'm appending some elements to it. All of a sudden, I find out that the next element to append should be the first child of E. What's the trick, how to do it? Method unshift doesn't work because E is an object, not array.
Long way would be to iterate through E's children and to move'em key++, but I'm sure that there is a prettier way.
var eElement; // some E DOM instance
var newFirstElement; //element which should be first in E
eElement.insertBefore(newFirstElement, eElement.firstChild);
2018 version - prepend
parent.prepend(newChild) // [newChild, child1, child2]
This is modern JS! It is more readable than previous options. It is currently available in Chrome, FF, and Opera.
The equivalent for adding to the end is append, replacing the old appendChild
parent.append(newChild) // [child1, child2, newChild]
Advanced usage
You can pass multiple values (or use spread operator ...).
Any string value will be added as a text element.
Examples:
parent.prepend(newChild, "foo") // [newChild, "foo", child1, child2]
const list = ["bar", newChild]
parent.append(...list, "fizz") // [child1, child2, "bar", newChild, "fizz"]
Related DOM methods
Read More - child.before and child.after
Read More - child.replaceWith
Mozilla Documentation
Can I Use
2017 version
You can use
targetElement.insertAdjacentElement('afterbegin', newFirstElement)
From MDN :
The insertAdjacentElement() method inserts a given element node at a given position relative to the element it is invoked upon.
position
A DOMString representing the position relative to the element; must be one of the following strings:
beforebegin: Before the element itself.
afterbegin: Just inside the element, before its first child.
beforeend: Just inside the element, after its last child.
afterend: After the element itself.
element
The element to be inserted into the tree.
In the family of insertAdjacent there is the sibling methods:
element.insertAdjacentHTML('afterbegin','htmlText')`
That can inject html string directly, like innerHTML but without override everything, so you can use it as a mini-template Engin and jump the oppressive process of document.createElement and even build a whole component with string manipulation process
element.insertAdjacentText for inject sanitize string into element . no more encode/decode
You can implement it directly i all your window html elements.
Like this :
HTMLElement.prototype.appendFirst = function(childNode) {
if (this.firstChild) {
this.insertBefore(childNode, this.firstChild);
}
else {
this.appendChild(childNode);
}
};
Accepted answer refactored into a function:
function prependChild(parentEle, newFirstChildEle) {
parentEle.insertBefore(newFirstChildEle, parentEle.firstChild)
}
Unless I have misunderstood:
$("e").prepend("<yourelem>Text</yourelem>");
Or
$("<yourelem>Text</yourelem>").prependTo("e");
Although it sounds like from your description that there is some condition attached, so
if (SomeCondition){
$("e").prepend("<yourelem>Text</yourelem>");
}
else{
$("e").append("<yourelem>Text</yourelem>");
}
I think you're looking for the .prepend function in jQuery. Example code:
$("#E").prepend("<p>Code goes here, yo!</p>");
I created this prototype to prepend elements to parent element.
Node.prototype.prependChild = function (child: Node) {
this.insertBefore(child, this.firstChild);
return this;
};
var newItem = document.createElement("LI"); // Create a <li> node
var textnode = document.createTextNode("Water"); // Create a text node
newItem.appendChild(textnode); // Append the text to <li>
var list = document.getElementById("myList"); // Get the <ul> element to insert a new node
list.insertBefore(newItem, list.childNodes[0]); // Insert <li> before the first child of <ul>
https://www.w3schools.com/jsref/met_node_insertbefore.asp