-1

I have tried to find answers and only stumbled over replaceWith Automatically Closes the Tag and Replace HR Element with Open Div - both finding first and last element and wrapping a div around.

In my case we have an HTML with multiple text in p elements, such as:

<p>
    [spoiler]
</p>
<p>
    Text to hide. 
</p>
<p>
    [/spoiler]<br />
</p>
<p>
    Text in-between.
</p>
<p>
    [spoiler]
</p>
<p>
    Second Text to hide. 
</p>
<p>
    [/spoiler]
</p>
<p>
    More Text …
</p>

Now I need to find the opening [spoiler] tags and replace their wrapping p tags with an opening <div class="spoiler">. Next I need to find the closing [/spoiler] tags and replace them with a closing </div>.

Jquery's replaceWith() always closes the inserted element.

So my simple approach does not work:

$(this).find('p:contains([spoiler])').replaceWith('<div class="qa-spoiler">');
$(this).find('p:contains([/spoiler])').replaceWith('</div>');

I have no control about the HTML markup.

How to do it?


PS: Changed the headline from "replaceWith without closing Tag and wrapping a Div around multiple p tags" to "How to replace an HTML tag with only an opening DIV and close it later on".

Avatar
  • 14,622
  • 9
  • 119
  • 198
  • Because you are inserting elements, you are not inserting html. Html is parsed and inserted into the dom. Dom elements don't have an opening and closing. They are just objects. – Taplar Jan 02 '18 at 15:19
  • You can only create whole elements within the DOM, ie. you cannot append a start and end tag separately. Your current logic is broken because the browser's HTML renderer will automatically add the start/end tags you missed when appending the new element. I'd suggest searching for a BBCode interpreter if that's your goal. You could even do it quite simply in Regex if you want to do this manually. – Rory McCrossan Jan 02 '18 at 15:19
  • Sounds like I need to change the HTML as string then. Which sounds complicated and error prone. – Avatar Jan 02 '18 at 15:21
  • I should also ask, why are you generating your markup in this fashion and trying to change it with javascript later? Why not just build it correctly in the first place? – Taplar Jan 02 '18 at 15:25
  • I am using an external editor and have no control over the `p` tags. That's why `[spoiler]` is within `p` tags. - I rephrased the question to "How to replace an HTML tag with only an opening DIV and close it later on" and added this information. – Avatar Jan 02 '18 at 15:27
  • Again, you are manipulating the Document Object Model. Not the markup on the source file. You are not replacing closing, opening tags. You are replacing whole dom objects. You have to think in that manner. – Taplar Jan 02 '18 at 15:36

1 Answers1

2

This logic finds all the elements between the p tags containing the opening and closing spoiler markers and wraps them in the div you want. It then goes back and removes the spoiler tags, effectively "replacing" them.

$('p:contains([spoiler])').each(function(){
 $(this).nextUntil('p:contains([/spoiler])').wrapAll('<div class="qa-spoiler">');
}).remove();

$('p:contains([/spoiler])').remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
    [spoiler]
</p>
<p>
    Text to hide. 
</p>
<p>
    Text to hide. 
</p>
<p>
    [/spoiler]<br />
</p>
<p>
    Text in-between.
</p>
<p>
    [spoiler]
</p>
<p>
    Second Text to hide. 
</p>
<p>
    [/spoiler]
</p>
<p>
    More Text …
</p>
Taplar
  • 24,788
  • 4
  • 22
  • 35