Javascript Append Child AFTER Element - javascript

I would like to append an li element after another li inside a ul element using javascript, This is the code I have so far..
var parentGuest = document.getElementById("one");
var childGuest = document.createElement("li");
childGuest.id = "two";
I am familiar with appendChild,
parentGuest.appendChild(childGuest);
However this appends the new element inside the other, and not after. How can I append the new element after the existing one? Thanks.
<ul>
<li id="one"><!-- where the new li is being put --></li>
<!-- where I want the new li -->
</ul>

You can use:
if (parentGuest.nextSibling) {
parentGuest.parentNode.insertBefore(childGuest, parentGuest.nextSibling);
}
else {
parentGuest.parentNode.appendChild(childGuest);
}
But as Pavel pointed out, the referenceElement can be null/undefined, and if so, insertBefore behaves just like appendChild. So the following is equivalent to the above:
parentGuest.parentNode.insertBefore(childGuest, parentGuest.nextSibling);

You need to append the new element to existing element's parent before element's next sibling. Like:
var parentGuest = document.getElementById("one");
var childGuest = document.createElement("li");
childGuest.id = "two";
parentGuest.parentNode.insertBefore(childGuest, parentGuest.nextSibling);
Or if you want just append it, then:
var parentGuest = document.getElementById("one");
var childGuest = document.createElement("li");
childGuest.id = "two";
parentGuest.parentNode.appendChild(childGuest);

If you are looking for a plain JS solution, then you just use insertBefore() against nextSibling.
Something like:
parentGuest.parentNode.insertBefore(childGuest, parentGuest.nextSibling);
Note that default value of nextSibling is null, so, you don't need to do anything special for that.
Update: You don't even need the if checking presence of parentGuest.nextSibling like the currently accepted answer does, because if there's no next sibling, it will return null, and passing null to the 2nd argument of insertBefore() means: append at the end.
Reference:
nextSibling
insertBefore
.
IF you are using jQuery (ignore otherwise, I have stated plain JS answer above), you can leverage the convenient after() method:
$("#one").after("<li id='two'>");
Reference:
jQuery after()

after is now a JavaScript method
MDN Documentation
Quoting MDN
The ChildNode.after() method inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just after this ChildNode. DOMString objects are inserted as equivalent Text nodes.
The browser support is Chrome(54+), Firefox(49+) and Opera(39+). It doesn't support IE and Edge.
Snippet
var elm=document.getElementById('div1');
var elm1 = document.createElement('p');
var elm2 = elm1.cloneNode();
elm.append(elm1,elm2);
//added 2 paragraphs
elm1.after("This is sample text");
//added a text content
elm1.after(document.createElement("span"));
//added an element
console.log(elm.innerHTML);
<div id="div1"></div>
In the snippet, I used another term append too

This suffices :
parentGuest.parentNode.insertBefore(childGuest, parentGuest.nextSibling || null);
since if the refnode (second parameter) is null, a regular appendChild is performed. see here : http://reference.sitepoint.com/javascript/Node/insertBefore
Actually I doubt that the || null is required, try it and see.

You could also do
function insertAfter(node1, node2) {
node1.outerHTML += node2.outerHTML;
}
or
function insertAfter2(node1, node2) {
var wrap = document.createElement("div");
wrap.appendChild(node2.cloneNode(true));
var node2Html = wrap.innerHTML;
node1.insertAdjacentHTML('afterend', node2Html);
}

Related

object HTMLDivElement to string [duplicate]

Imagine I have the following HTML:
<div><span><b>This is in bold</b></span></div>
I want to get the HTML for the div, including the div itself. Element.innerHTML only returns:
<span>...</span>
Any ideas? Thanks
Use outerHTML:
var el = document.getElementById( 'foo' );
alert( el.outerHTML );
Expanding on jldupont's answer, you could create a wrapping element on the fly:
var target = document.getElementById('myElement');
var wrap = document.createElement('div');
wrap.appendChild(target.cloneNode(true));
alert(wrap.innerHTML);
I am cloning the element to avoid having to remove and reinsert the element in the actual document. This might be expensive if the element you wish to print has a very large tree below it, though.
First, put on element that wraps the div in question, put an id attribute on the element and then use getElementById on it: once you've got the lement, just do 'e.innerHTML` to retrieve the HTML.
<div><span><b>This is in bold</b></span></div>
=>
<div id="wrap"><div><span><b>This is in bold</b></span></div></div>
and then:
var e=document.getElementById("wrap");
var content=e.innerHTML;
Note that outerHTML is not cross-browser compatible.
old question but for newcomers that come around :
document.querySelector('div').outerHTML
You'll want something like this for it to be cross browser.
function OuterHTML(element) {
var container = document.createElement("div");
container.appendChild(element.cloneNode(true));
return container.innerHTML;
}
If you want a lighter footprint, but a longer script, get the elements innerHTML and only create and clone the empty parent-
function getHTML(who,lines){
if(!who || !who.tagName) return '';
var txt, ax, str, el= document.createElement('div');
el.appendChild(who.cloneNode(false));
txt= el.innerHTML;
ax= txt.indexOf('>')+1;
str= txt.substring(0, ax)+who.innerHTML+ txt.substring(ax);
el= null;
return lines? str.replace(/> *</g,'>\n<'): str;
//easier to read if elements are separated
}
var x = $('#container').get(0).outerHTML;
as outerHTML is IE only, use this function:
function getOuterHtml(node) {
var parent = node.parentNode;
var element = document.createElement(parent.tagName);
element.appendChild(node);
var html = element.innerHTML;
parent.appendChild(node);
return html;
}
creates a bogus empty element of the type parent and uses innerHTML on it and then reattaches the element back into the normal dom
define function outerHTML based on support for element.outerHTML:
var temp_container = document.createElement("div"); // empty div not added to DOM
if (temp_container.outerHTML){
var outerHTML = function(el){return el.outerHTML||el.nodeValue} // e.g. textnodes do not have outerHTML
} else { // when .outerHTML is not supported
var outerHTML = function(el){
var clone = el.cloneNode(true);
temp_container.appendChild(clone);
outerhtml = temp_container.innerHTML;
temp_container.removeChild(clone);
return outerhtml;
};
};
var el = document.getElementById('foo');
el.parentNode.innerHTML;

Get the tagName element inside class

I want to get the element of a inside class and change it.
My HTML is:
<div class="alignleft">
« Older Entries
</div>
I want to change Older Entries to Previous.
My JavaScript code is:
var oldentries = document.querySelector('.alignleft');
var ainside = document.getElementsByTagName('a');
oldentries.ainside.innerHTML = "Previous";
but that gives me undefined.
Once you use Document.querySelector() to get the elements with class '.alignleft' you can also do oldentries.querySelector('a'); to get the 'a' element within oldentries and then change the element.innerHTML:
var oldentries = document.querySelector('.alignleft'),
ainside = oldentries.querySelector('a');
ainside.innerHTML = 'Previous';
<div class="alignleft">
« Older Entries
</div>
You need to update the textContent property of the <a> element.
Working Example:
var linkElement = document.querySelector('.alignleft a');
linkElement.textContent = 'Previous';
<div class="alignleft">
<a>Older Entries</a>
</div>
You can look for your element using a signle call to querySelector by using a more precise selector : Directly use .alignLeft a instead of doing it twice.
This code works :
var entries = document.querySelector('.alignLeft a');
entries.innerHTML = "Previous"
Your code would render out to something like
document.querySelector('.alignleft').document.getElementsByTagName('a').innerHTML = "Previous";
Also, getElementsByTagName('a') would render an Array not an object which you can apply .innerHTML to.
var ainside = document.querySelector('.alignlef a'); // Select first occurance of a inside the first occurance of .alignleft in the document
ainside.innerHTML = "Previous";
document.getElementsByTagName returns a HTML Collection. So you need to iterate over it (in your case it would be the first entry).
var oldentries = document.querySelector('.alignleft');
var ainside = document.getElementsByTagName('a');
for(i=0;i<ainside.length;i++) {
ainside[i].innerHTML = "Previous";
}

Javascript regex to replace text div and < >

var text='<div id="main"><div class="replace">< **My Text** ></div><div>Test</div></div>'
I want to replace div with class="replace" and html entities < > comes inside that div with some other text.
I.e the output :
'<div id="main"> Hello **My Text** Hello <div>Test</div> </div>'
I've tried
var div = new RegExp('<[//]{0,1}(div|DIV)[^><]*>', 'g');
text = text.replace(div, "Hello");
but this will replace all div.
Any help gratefully received!
If a Jquery solution is acceptable:
text = $(text) // Convert HTML string to Jquery object
.wrap("<div />") // Wrap in a container element to make...
.parent() // the whole element searchable
.find("div.replace") // Find <div class="replace" />
.each(function() // Iterate over each div.replace
{
$(this)
.replaceWith($(this).html() // Replace div with content
.replace("<", "<sometext>")
.replace(">", "</sometext>")); // Replace text
})
.end().html(); // return html of $(text)
This sets text to:
<div id="main"><sometext> My Text </sometext><div>Test</div></div>
And to replace it back again:
text = text.replace('<sometext>', '<div class="replace"><')
.replace('</sometext>', '></div>');
http://api.jquery.com/jquery/#jQuery2
http://api.jquery.com/each/
http://api.jquery.com/find/
http://api.jquery.com/html/
In pure JS it will be something like this:
var elements = document.getElementsByClassName('replace');
var replaceTag = document.createElement('replacetext');
for (var i = elements.length - 1; i >= 0; i--) {
var e = elements[i];
e.parentNode.replaceChild(replaceTag, e);
};​
Here is one crazy regex which matches what you want:
var text='<div id="main"><div class="replace">< **My Text** ></div><div>Test</div></div>'
var r = /(<(div|DIV)\s+class\s*?=('|")\s*?replace('|")\s*?>)(\s*?<)(.*?)(>\s*?)(<\/(div|DIV)\s*?>)/g;
The whole replacement can be made with:
text.replace(r, function () {
return 'Hello' + arguments[6] + 'Hello';
});
Please let me know if there are issues with the solution :).
Btw: I'm totally against regexes like the one in the answer...If you have made it with that complex regex there's probably better way to handle the problem...
Consider using the DOM instead; you already have the structure you want, so swap out the node itself (borrowing heavily from #maxwell's code, but moving children around as well):
var elements = document.getElementsByClassName('replace');
for(var i = elements.length-1; i>= 0; --i) {
var element = elements[i];
var newElement = document.createElement('replacetext');
var children = element.childNodes;
for(var ch = 0; ch < children.length; ++i) {
var child = children[ch];
element.removeChild(child);
newElement.appendChild(child);
}
element.parentNode.insertBefore(newElement,element);
element.parentNode.removeChild(element);
}
For each element of the given class, then, it will move each of its children over to the new element before using that element's position to insert the new element and finally removing itself.
My only questionmark is whether the modification of items in the array return by getElementByClassName will cause problems; it might need an extra check to see if the element is valid before processing it, or you may prefer to write this as a recursive function and process the tree from deepest node first.
It may seem like more work, but this should be faster (no re-parsing of the html after you've changed it, element moves are just reference value assignments) and much more robust. Attempting to parsing HTML may damage your health.
Rereading the question (always a good plan), you begin with the text in a string. If that is truly the start point (i.e. you're not just pulling that out of an innerHTML value), then to use the above just create a temporary parent element:
var fosterer = document.createElement('div');
fosterer.innerHTML = text; // your variable from the question
And then proceed using fosterer.getElementsByClassName.

How to correctly use innerHTML to create an element (with possible children) from a html string?

Note: I do NOT want to use any framework.
The goal is just to create a function that will return an element based on an HTML string.
Assume a simple HTML Document like such:
<html>
<head></head>
<body>
</body>
</html>
All functions mentioned are in included the head section and all DOM creation/manipulation is done at the end of the body in a script tag.
I have a function createElement that takes a well formed HTML String as an argument. It goes like this:
function createElement(str)
{
var div = document.createElement('div');
div.innerHTML = str;
return div.childNodes;
}
Now this functions works great when you call it like such:
var e = createElement('<p id="myId" class="myClass">myInnerHTML</p>');
With the minor (possibly HUGE) problem that the element created isn't a 'true' element, it still has a parentNode of 'div'. If anyone knows how to fix that, then that would be awesome.
Now if I call the same function with a more complex string:
var e = createElement('<p id="myId" class="myClass">innerHTML<h2 id="h2ID" class="h2CLASS">Heading2</h2></p>');
It creates TWO children instead of ONE child with another child having another child.Once you do div.innerHTML = str. The innerHTML instead of
`<p id="myId" class="myClass">innerHTML <h2 id="h2ID" class="h2CLASS">Heading2</h2> </p>`
turns to
`<p id="myId" class="myClass">innerHTML</p> <h2 id="h2ID" class="h2CLASS">Heading2</h2>`
Questions:
Can I somehow get an element without a parent node after using .innerHTML?
Can I (in the case of the slightly complex string) get my function to return ONE element with the appropriate child instead of two elements. [It actually returns three, <p.myClass#myId>,<h2.h2CLASS#h2ID>, and another <p>]
This is similar to the answer from palswim, except that it doesn't bother with creating a clone, and uses a while() loop instead, always appending the node at [0].
function createElement( str ) {
var frag = document.createDocumentFragment();
var elem = document.createElement('div');
elem.innerHTML = str;
while (elem.childNodes[0]) {
frag.appendChild(elem.childNodes[0]);
}
return frag;
}
You'd have to attach the new element somewhere. Try using a DocumentFragment object in conjunction with the div you created:
function createElement(str) {
var div = document.createElement('div');
div.innerHTML = str;
var container = document.createDocumentFragment();
for (var i=0; i < div.childNodes.length; i++) {
var node = div.childNodes[i].cloneNode(true);
container.appendChild(node);
}
return container.childNodes;
}
It's more overhead, but it does what you want. Note that DOM elements' .insertAdjacentHTML member function is coming in HTML5.
For that complex string you passed, it isn't valid XHTML syntax - you can't have a block element as a child of <p> (<h2> is a block level element).

Get the string representation of a DOM node

Javascript: I have the DOM representation of a node (element or document) and I'm looking for the string representation of it. E.g.,
var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));
should yield:
get_string(el) == "<p>Test</p>";
I have the strong feeling, that I'm missing something trivially simple, but I just don't find a method that works in IE, FF, Safari and Opera. Therefore, outerHTML is no option.
You can create a temporary parent node, and get the innerHTML content of it:
var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));
var tmp = document.createElement("div");
tmp.appendChild(el);
console.log(tmp.innerHTML); // <p>Test</p>
EDIT:
Please see answer below about outerHTML. el.outerHTML should be all that is needed.
What you're looking for is 'outerHTML', but wee need a fallback coz it's not compatible with old browsers.
var getString = (function() {
var DIV = document.createElement("div");
if ('outerHTML' in DIV)
return function(node) {
return node.outerHTML;
};
return function(node) {
var div = DIV.cloneNode();
div.appendChild(node.cloneNode(true));
return div.innerHTML;
};
})();
// getString(el) == "<p>Test</p>"
You'll find my jQuery plugin here: Get selected element's outer HTML
I dont think you need any complicated script for this. Just use
get_string=(el)=>el.outerHTML;
Under FF you can use the XMLSerializer object to serialize XML into a string. IE gives you an xml property of a node. So you can do the following:
function xml2string(node) {
if (typeof(XMLSerializer) !== 'undefined') {
var serializer = new XMLSerializer();
return serializer.serializeToString(node);
} else if (node.xml) {
return node.xml;
}
}
Use Element#outerHTML:
var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));
console.log(el.outerHTML);
It can also be used to write DOM elements. From Mozilla's documentation:
The outerHTML attribute of the element DOM interface gets the serialized HTML fragment describing the element including its descendants. It can be set to replace the element with nodes parsed from the given string.
https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
Try
new XMLSerializer().serializeToString(element);
Use element.outerHTML to get full representation of element, including outer tags and attributes.
You can simply use outerHTML property over the element. It will return what you desire.
Let's create a function named get_string(element)
var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));
function get_string(element) {
console.log(element.outerHTML);
}
get_string(el); // your desired output
If your element has parent
element.parentElement.innerHTML
I've found that for my use-cases I don't always want the entire outerHTML. Many nodes just have too many children to show.
Here's a function (minimally tested in Chrome):
/**
* Stringifies a DOM node.
* #param {Object} el - A DOM node.
* #param {Number} truncate - How much to truncate innerHTML of element.
* #returns {String} - A stringified node with attributes
* retained.
*/
function stringifyEl(el, truncate) {
var truncateLen = truncate || 50;
var outerHTML = el.outerHTML;
var ret = outerHTML;
ret = ret.substring(0, truncateLen);
// If we've truncated, add an elipsis.
if (outerHTML.length > truncateLen) {
ret += "...";
}
return ret;
}
https://gist.github.com/kahunacohen/467f5cc259b5d4a85eb201518dcb15ec
While outerHTML is usually the answer, for Attr and Text(Child classes of the Node interface), there are other properties:
(<Element>x).outerHTML
(<Text>x).data
(<Attr>x).value;
See https://developer.mozilla.org/en-US/docs/Web/API/Node for more types of Nodes such as DocumentFragment and Comment
I have wasted a lot of time figuring out what is wrong when I iterate through DOMElements with the code in the accepted answer. This is what worked for me, otherwise every second element disappears from the document:
_getGpxString: function(node) {
clone = node.cloneNode(true);
var tmp = document.createElement("div");
tmp.appendChild(clone);
return tmp.innerHTML;
},
if using react:
const html = ReactDOM.findDOMNode(document.getElementsByTagName('html')[0]).outerHTML;

Categories

Resources