Home > other >  How to replace nested span to div element in JQuery?
How to replace nested span to div element in JQuery?

Time:12-08

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  ');
            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

CodePudding user response:

Code hint is in the comments where changes have been made.

    
<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"  data-fact="619959c0062c677faebd7b55">
    <span xvid="ca5635a4e4de332d7dc3036a68e57009"  data-fact="619959c0062c677faebd7b57">November 1, 2021</span>
  </span>
</p>
`
console.log(replaceTags(htmlData));

function replaceTags (htmlData) {
//var $factElem = $elm.find('[data-fact]');
// alternative way to make above checks since htmlData is a string at this point of time so just simply search the string to determin id data attribute exists.

  if(htmlData.toLowerCase().includes("data-fact")){

            htmlData = htmlData.replace(/<span/g, '<div  ');
            htmlData = htmlData.replace(/<\/span>/g, '<\/div>');
             
        }
//no need to else it since you would be throwing out htmlData in any case. 
            return htmlData;
        
   }
    
    </script>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

just in case data-fact is present but no span tag then it would make the replacement as examplified below.

<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">
  <p xvid="2b80c95cd4b851345ba4c3fe6937d30b" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate"  data-fact="619959c0062c677faebd7b55">
    <p xvid="ca5635a4e4de332d7dc3036a68e57009"  data-fact="619959c0062c677faebd7b57">November 1, 2021</p>
  </p>
</p>
`
console.log(replaceTags(htmlData));

function replaceTags (htmlData) {
//var $factElem = $elm.find('[data-fact]');
// alternative way to make above checks since htmlData is a string at this point of time so just simply search the string to determin id data attribute exists.

  if(htmlData.toLowerCase().includes("data-fact")){

            htmlData = htmlData.replace(/<span/g, '<div  ');
            htmlData = htmlData.replace(/<\/span>/g, '<\/div>');
             
        }
//no need to else it since you would be throwing out htmlData in any case. 
            return htmlData;
        
   }
    
    </script>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

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>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

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.

// While there are still more span's in the p
while ($('p span[data-fact]').length > 0) {
  // get the next span to replace with a div
  const $span = $($('p 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);
}

console.log($('p').html());
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>
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

NOTE: it is invalid HTML to have div tag inside p so one should probably replace the p tag too.

  • Related