I'm trying to check whether the given htmlData has nested(parent,child not siblings) span elements with attribute name data-fact or not.
if it does then replace it with span to div with class='inline-span' pass all the attributes with it.
else just return the htmlData
var htmlData = `<p style="font: 10pt Times New Roman, Times, Serif; margin: 0pt 0;" xvid="f5ea22ec52553bc61525766b631e126f">
<span xvid="2b80c95cd4b851345ba4c3fe6937d30b" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate" class="manual-map" data-fact="619959c0062c677faebd7b55">
<span xvid="ca5635a4e4de332d7dc3036a68e57009" class="wrapped manual-map" data-fact="619959c0062c677faebd7b57">November 1, 2021</span>
</span>
</p>
`
replaceTags(htmlData)
function replaceTags (htmlData) {
var $elm = $(htmlData).find("span[data-fact]");
var $nestedElm = $elm.children().length > 1;
if($nestedElm){
htmlData = htmlData.replace(/<span/g, '<div class="inline-span" ');
htmlData = htmlData.replace(/<\/span>/g, '<\/div>');
}else{
return htmlData;
}
},
The output htmlData i want is something like this
<p style="font: 10pt Times New Roman, Times, Serif; margin: 0pt 0;" xvid="f5ea22ec52553bc61525766b631e126f">
<div class='inline-span' xvid="2b80c95cd4b851345ba4c3fe6937d30b" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate" class="manual-map" data-fact="619959c0062c677faebd7b55">
<div class='inline-span' xvid="ca5635a4e4de332d7dc3036a68e57009" class="wrapped manual-map" data-fact="619959c0062c677faebd7b57">November 1, 2021</div>
</div>
</p>
Here i'm not able to find is the span element is nested or not and then the conversion of how can i pass the class='inline-span' with all the previous attributes to the div.
PS: answer i want is in JQuery
It is typically a bad idea to do string replacement to change HTML. You should instead use the tools of jquery to manipulate the DOM. Which is safer and less error prone.
const replaceTags = ($tagToReplace) => {
// create a copy of the htmlData
const $cloned = $tagToReplace.clone();
// While there are still more span's in the p
while ($cloned.find('span[data-fact]').length > 0) {
// get the next span to replace with a div
const $span = $($cloned.find('span[data-fact]')[0]);
// create the new div
const $newDiv = $('<div>');
// copy the span's html into the div
$newDiv.html($span.html());
// For each attribute in the span ...
$.each($span[0].attributes, (_ , attr) => {
// ... set the new div to have the span's attribute.
$newDiv.attr(attr.name, attr.value);
});
// new div needs 'inline-span' property.
$newDiv.addClass('inline-span');
// finally replace the span with the new div
$span.replaceWith($newDiv);
}
return $cloned;
}
// select tag to replace
const $tagToReplace = $('p');
// get the new cloned tag
const $newHtmlData = replaceTags($tagToReplace);
// add the cloned to the body
$('body').append($newHtmlData);
// print that new elements html
console.log($newHtmlData[0].outerHTML);
p {
padding: 8px;
border: 1px dashed green;
}
span[data-fact] {
border: 1px solid red;
padding: 3px;
}
div[data-fact] {
border: 1px solid blue;
padding: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p style="font: 10pt Times New Roman, Times, Serif; margin: 0pt 0;" xvid="f5ea22ec52553bc61525766b631e126f">
<span xvid="2b80c95cd4b851345ba4c3fe6937d30b" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate" class="manual-map" data-fact="619959c0062c677faebd7b55">
<span xvid="ca5635a4e4de332d7dc3036a68e57009" class="wrapped manual-map" data-fact="619959c0062c677faebd7b57">November 1, 2021</span>
</span>
</p>
NOTE: it is invalid HTML to have div tag inside p so one should probably replace the p tag too.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script> var htmlData = `<p style="font: 10pt Times New Roman, Times, Serif; margin: 0pt 0;" xvid="f5ea22ec52553bc61525766b631e126f">
<span xvid="2b80c95cd4b851345ba4c3fe6937d30b" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate" class="manual-map" data-fact="619959c0062c677faebd7b55">
<span xvid="ca5635a4e4de332d7dc3036a68e57009" class="wrapped manual-map" data-fact="619959c0062c677faebd7b57">November 1, 2021</span>
</span>
</p>
`
console.log(replaceTags(htmlData, "span span[data-fact]","div"));
//a very handy function from Matt Basta to rplace tag names cannot be done on the fly without such functions
function replaceElement(source, newType) {
// Create the document fragment
const frag = document.createDocumentFragment();
// Fill it with what's in the source element
while (source.firstChild) {
frag.appendChild(source.firstChild);
}
// Create the new element
const newElem = document.createElement(newType);
// Empty the document fragment into it
newElem.appendChild(frag);
// Replace the source element with the new element on the page
source.parentNode.replaceChild(newElem, source);
}
//we now use our function as warper on above function.
function replaceTags (htmlData,whatToChange,withWhat) {
var fragment = document.createElement('just');
fragment.innerHTML=htmlData;
var found = fragment.querySelector(whatToChange);
if(found){
replaceElement(fragment.querySelector(whatToChange), withWhat);}
return fragment.innerHTML;
}
</script>
Getting as to what you want here is more logical solution that mixes bunch of search logics to do the job. Not perfect but its close
I did some changes related to Find in HTML element and in replace jquery code here is a working demo hope it will be helpful for you.
you can direcatly replace all html with like
htmlData = htmlData.replace($factElem[0].outerHTML, 'div html');
using $factElem[0].outerHTML you can find element containing [data-fact] html.
yes you can check only using data-fact and replace it with div there is no span needed
I updated Code Please check now.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("button").click(function () {
var htmlData = '<p style="font: 10pt Times New Roman, Times, Serif; margin: 0pt 0;" xvid="f5ea22ec52553bc61525766b631e126f"><span xvid="2b80c95cd4b851345ba4c3fe6937d30b" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate" class="manual-map" data-fact="619959c0062c677faebd7b55"><span xvid="ca5635a4e4de332d7dc3036a68e57009" class="wrapped manual-map" data-fact="619959c0062c677faebd7b57">November 1, 2021</span></span></p>'
replaceTags(htmlData);
});
});
function replaceTags(htmlData) {
var $factElem = $(htmlData).find('[data-fact]');
if ($factElem) {
htmlData = htmlData.replace($factElem[0].outerHTML, '<div class="inline-span" xvid="2b80c95cd4b851345ba4c3fe6937d30b" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate" class="manual-map" data-fact="619959c0062c677faebd7b55"><div class="inline-span" xvid="ca5635a4e4de332d7dc3036a68e57009" class="wrapped manual-map" data-fact="619959c0062c677faebd7b57">November 1, 2021</div></div>');
$("#append").empty().append(htmlData);
alert(htmlData);
} else {
$("#append").empty().append(htmlData);
}
}
</script>
</head>
<body>
<div id="append"></div>
<button>Click me to Replace!!</button>
</body>
</html>