How To Extract Nested Html Element To Same Level In Js
Solution 1:
You can clone original node using .cloneNode()
with parameter true
; iterate the .childNodes
of parent <div>
, if node .previousElementSibling
is not null
and .parentElement
is not original parent element passed to function push .parentElement
.tagName
and .textContent
to array, else .nodeName
is #text
, push .textContent
to an array; if .nodeName
does not equal #text
and only #text
nodes exist within element, push .outerHTML
to array; if node .tagName
does not equal #text
and node .firstChild
node is #text
, push node .tagName
, .firstChild
.textContent
, closing tag to array, remove .firstChild
; else recursively call function
const clone = document.querySelector("div").cloneNode(true);
let flattenNodes = (el, not = el, res = []) => {
for (let node of el.childNodes) {
if (node.nodeName === "#text" && !node.childNodes.length) {
if (node.previousElementSibling && node.parentElement !== not) {
let tag = node.parentElement.tagName.toLowerCase();
res.push(`<${tag}>${node.textContent}</${tag}>`);
} else {
res.push(node.textContent);
}
}
if (node.nodeName !== "#text"
&& Array.from(node.childNodes).every(e => e.nodeName === "#text")) {
res.push(node.outerHTML);
} else {
if (node.tagName && node.tagName !== "#text"
&& node.firstChild.nodeName === "#text") {
let tag = node.tagName.toLowerCase();
res.push(`<${tag}>${node.firstChild.textContent}</${tag}>`);
node.firstChild.remove();
flattenNodes(node, not, res);
}
}
}
return res
}
let res = flattenNodes(clone);
document.querySelector("pre")
.textContent = res.join("");
<div>
<p>
some text on here 1
<i>
some italic
<b>text</b>
here
</i> text text text
</p>
<b>
some bold text on here
</b>
</div>
<pre></pre>
Solution 2:
How often does this operation need to happen? Is it a performance hazard or is it a rare occasion?
If it's not a bottleneck, you can just select all descendants of your div and append them to the div. When you append an existing node, it will be automatically moved to the appropriate position.
const myDiv = document
.querySelector('#my-div')
const allDescendants = Array.from(myDiv.getElementsByTagName('*'))
allDescendants.forEach(d => {
myDiv.appendChild(d);
});
console.log(myDiv.innerHTML);
<div id="my-div">
<p>
some text on here 1
<i>
some italic
<b>text</b>
here
</i> text text text
</p>
<b>
some bold text on here
</b>
</div>
Not sure if this is intentional but based on your example, you only want to move elements and leave other nodes such as text nodes where they were. A specific example is the here
text portion in the first <i>
.
To achieve this, you can perform a pre-order DFS through all descendants, and build the new flat tree. Once finished, replace the old element with the new one.
const myDiv = document
.querySelector('#my-div')
const flatDiv = document.createElement('div')
function recurseAndFlatten(parent) {
parent.childNodes.forEach(child => {
if (child.nodeType === Node.ELEMENT_NODE) {
flatDiv.appendChild(child);
recurseAndFlatten(child);
}
});
}
recurseAndFlatten(myDiv);
myDiv.replaceWith(flatDiv);
console.log(flatDiv.innerHTML);
<div id="my-div">
<p>
some text on here 1
<i>
some italic
<b>text</b>
here
</i> text text text
</p>
<b>
some bold text on here
</b>
</div>
Post a Comment for "How To Extract Nested Html Element To Same Level In Js"