Using jQuery to replace one tag with another

JavascriptJqueryReplace

Javascript Problem Overview


Goal:

Using jQuery, I'm trying to replace all the occurrences of:

<code> ... </code>

with:

<pre> ... </pre>
My solution:

I got as far as the following,

$('code').replaceWith( "<pre>" + $('code').html() + "</pre>" );
The problem with my solution:

but the issues is that it's replacing everything between the (second, third, fourth, etc)"code" tags with the content between the first "code" tags.

e.g.

<code> A </code>
<code> B </code>
<code> C </code>

becomes

<pre> A </pre>
<pre> A </pre>
<pre> A </pre>

I think I need to use "this" and some sort of function but I'm afraid I'm still learning and don't really understand how to piece a solution together.

Javascript Solutions


Solution 1 - Javascript

You can pass a function to .replaceWith [docs]:

$('code').replaceWith(function(){
    return $("<pre />", {html: $(this).html()});
});

Inside the function, this refers to the currently processed code element.

DEMO

Update: There is no big performance difference, but in case the code elements have other HTML children, appending the children instead of serializing them feels to be more correct:

$('code').replaceWith(function(){
    return $("<pre />").append($(this).contents());
});

Solution 2 - Javascript

This is much nicer:

$('code').contents().unwrap().wrap('<pre/>');

Though admittedly Felix Kling's solution is approximately twice as fast:

Solution 3 - Javascript

It's correct that you'll always obtain the first code's contents, because $('code').html() will always refer to the first element, wherever you use it.

Instead, you could use .each to iterate over all elements and change each one individually:

$('code').each(function() {
    $(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );
    // this function is executed for all 'code' elements, and
    // 'this' refers to one element from the set of all 'code'
    // elements each time it is called.
});

Solution 4 - Javascript

Try this:

$('code').each(function(){

    $(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );

});

http://jsfiddle.net/mTGhV/

Solution 5 - Javascript

How about this?

$('code').each(function () {
    $(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );
});

Solution 6 - Javascript

Building up on Felix's answer.

$('code').replaceWith(function() {
	var replacement = $('<pre>').html($(this).html());
	for (var i = 0; i < this.attributes.length; i++) {
		replacement.attr(this.attributes[i].name, this.attributes[i].value);
	}
	return replacement;
});

This will reproduce the attributes of the code tags in the replacement pre tags.

Edit: This will replace even those code tags that are inside the innerHTML of other code tags.

function replace(thisWith, that) {
	$(thisWith).replaceWith(function() {
		var replacement = $('<' + that + '>').html($(this).html());
		for (var i = 0; i < this.attributes.length; i++) {
			replacement.attr(this.attributes[i].name, this.attributes[i].value);
		}
		return replacement;
	});
	if ($(thisWith).length>0) {
		replace(thisWith, that);
	}
}

replace('code','pre');

Solution 7 - Javascript

As of jQuery 1.4.2:

$('code').replaceWith(function(i,html) {
  return $('<pre />').html(html);
});​

You can then select the new elements:

$('pre').css('color','red');

Source: http://api.jquery.com/replaceWith/#comment-45493689

jsFiddle: http://jsfiddle.net/k2swf/16/

Solution 8 - Javascript

If you were using vanilla JavaScript you would:

  • Create the new element
  • Move the children of old element into the new element
  • Insert the new element before the old one
  • Remove the old element

Here is jQuery equivalent of this process:

$("code").each(function () {
    $("<pre></pre>").append(this.childNodes).insertBefore(this);
    $(this).remove();
});

Here is the jsperf URL:
http://jsperf.com/substituting-one-tag-for-another-with-jquery/7

PS: All solutions that use .html() or .innerHTML are destructive.

Solution 9 - Javascript

Another short & easy way:

$('code').wrapInner('<pre />').contents();

Solution 10 - Javascript

All answers given here assume (as the question example indicates) that there are no attributes in the tag. If the accepted answer is ran on this:

<code class='cls'>A</code>

if will be replaced with

<pre>A</pre>

What if you want to keep the attributes as well - which is what replacing a tag would mean... ? This is the solution:

$("code").each( function(){
    var content = $( "<pre>" );

    $.each( this.attributes, function(){ 
         content.attr( this.name, this.value );
    } );

    $( this ).replaceWith( content );
} );

Solution 11 - Javascript

$('code').each(function(){
	$(this).replaceWith( "<pre>" + $(this).html()  + "</pre>" );
	});

Best and clean way.

Solution 12 - Javascript

You could use jQuery's html function. Below is a sample the replaces a code tag with a pre tag while retaining all of the attributes of the code.

    $('code').each(function() {
        var temp=$(this).html();
        temp=temp.replace("code","pre");
        $(this).html(temp);
    });

This could work with any set of html element tags that needed to be swapped while retaining all the attributes of the previous tag.

Solution 13 - Javascript

Made jquery plugin, maintaining attributes also.

$.fn.renameTag = function(replaceWithTag){
  this.each(function(){
		var outerHtml = this.outerHTML;
		var tagName = $(this).prop("tagName");
		var regexStart = new RegExp("^<"+tagName,"i");
		var regexEnd = new RegExp("</"+tagName+">$","i")
		outerHtml = outerHtml.replace(regexStart,"<"+replaceWithTag)
		outerHtml = outerHtml.replace(regexEnd,"</"+replaceWithTag+">");
		$(this).replaceWith(outerHtml);
	});
	return this;
}

Usage:

$('code').renameTag('pre')

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjonView Question on Stackoverflow
Solution 1 - JavascriptFelix KlingView Answer on Stackoverflow
Solution 2 - JavascriptJens RolandView Answer on Stackoverflow
Solution 3 - JavascriptpimvdbView Answer on Stackoverflow
Solution 4 - JavascriptKokosView Answer on Stackoverflow
Solution 5 - JavascriptTae-Sung ShinView Answer on Stackoverflow
Solution 6 - JavascripttewathiaView Answer on Stackoverflow
Solution 7 - JavascriptSimonView Answer on Stackoverflow
Solution 8 - JavascriptSalman AView Answer on Stackoverflow
Solution 9 - JavascriptFabian von EllertsView Answer on Stackoverflow
Solution 10 - JavascriptpatrickView Answer on Stackoverflow
Solution 11 - JavascriptNimekView Answer on Stackoverflow
Solution 12 - JavascriptControlAltDeleteView Answer on Stackoverflow
Solution 13 - JavascriptJagdish IdhateView Answer on Stackoverflow