4

I would like use the function wrap of jquery, or maybe with an other solution, but I need to wrap a content of div, with exclude specific tag like <sup> <i> <strong>. I explain with an example bellow

I have this :

<div>
   my test without tag<sup>1</sup> and the end of sentence.
   <p>text with tag p <br />
      break line
   </p>
   Second sentence without <i>tag</i> and the end.
<div> 

I would like this :

<div>
       <p>my test without tag<sup>1</sup> and the end of sentence.</p>
       <p>text with tag p <br />
          break line
       </p>
       <p>Second sentence without <i>tag</i> and the end.<p>
<div> 

So I do this in JS with JQuery,

$( "div" )
   .contents()
   .filter(function(){
      return this.nodeType !== 1;
   })
   .wrap( "<p></p>" );

But this JS do this :

<div>
   <p>my test without tag</p>
   <sup>1</sup>
   <p> and the end of sentence.</p>
   <p>text with tag p <br>
    break line
   </p>
   <p>Second sentence without </p><i>tag</i><p> and the end.</p>
</div>

I create this jsFiddle

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
Greg
  • 826
  • 5
  • 21

3 Answers3

3

function wrapElements(elements){
    $(elements).wrapAll('<p></p>');
}

$('div').each(function(){
    var elementsToWrap=[];
    var contents=$(this).contents();
    contents.each(function(){
        if($(this).text().trim()){
            if(this.nodeName!='P'){
                elementsToWrap.push(this);
            }else{
                wrapElements(elementsToWrap)
                elementsToWrap=[];
            }
        }
    });
    if(elementsToWrap.length)
    wrapElements(elementsToWrap);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
   my test without tag<sup>1</sup> and the end of sentence.
   <p>text with tag p <br />
      break line
   </p>
   Second sentence without <i>tag</i> and the end.
</div>

Have a look at the above code. it produces the correct output. but i am sure it can be further improved.

Note: i have used P tag to compare if the tag is paragraph tag if not then i am holding it till i get the next P tag and i wrap all in a P tag. (there may be many other logic to do this)

Inus Saha
  • 1,918
  • 11
  • 17
  • Damn, you beat me to it. ;) You can just use `this.nodeName` inside the callback, no need for function arguments. Also nicer if you define a function to wrap the elements and call it in two places. – DarthJDG Jun 20 '18 at 13:15
  • @DarthJDG thanks :). improved answer as suggested by you. – Inus Saha Jun 20 '18 at 13:20
  • 1
    There is an issue if content starts/ends with a paragraph and there are spaces in the markup. In that case, the first/last content elements will be text nodes full of white space characters (spaces, tabs, new lines), resulting in an empty paragraph in the output. Might need to filter those out first. – DarthJDG Jun 20 '18 at 13:38
  • Hi, thanks for your help, there is an other issue, if we have a div with only text with tag. See here https://jsfiddle.net/3ydfe9kw/ – Greg Jun 20 '18 at 14:06
  • 2
    I have updated my answer and you can take a look here: https://jsfiddle.net/3ydfe9kw/2/ – Inus Saha Jun 20 '18 at 14:21
  • Its works but I don't reproduce the issue reported by DarthDG – Greg Jun 20 '18 at 15:15
  • its because i have corrected it. i have added `trim()` to check for content and only use those elements to wrap – Inus Saha Jun 20 '18 at 15:29
  • if its working then i request you to please accept it as answer. – Inus Saha Jun 20 '18 at 15:31
1

Basically I feel that there are no need for the usage of wrap at all. I think the best way for you would be to treat html as String and perform replacement of the all occurrences by using RegExp (which is kind of (\w[uniq tag1|uniq tag1]\w) text.

See more about that on How to replace all occurrences of a string in JavaScript?

Another option would be to create recursive function which retain previous and test for current node and next node. By using of such function you can create fresh html and then replace it with $(el).html(newHtml)

Andriy Ivaneyko
  • 20,639
  • 6
  • 60
  • 82
1

Considering that you know the text that you need to wrap with tag You could do the following

var op = "<div> my test without tag<sup>1</sup> and the end of sentence.<p>text with tag p <br /></p>Second sentence without <i>tag</i> and the end.<div>"
var text = 'my test without tag<sup>1</sup> and the end of sentence.' // The text that you need to wrap around
var re = new RegExp('('+text+')', 'i');
op.replace(re,'<p>$1</p>')
prajnavantha
  • 1,111
  • 13
  • 17