Using jQuery to replace one tag with another

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.

Answers:

Answer

This is much nicer:

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

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

Answer

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.
});
Answer

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

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/

Answer

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.

Answer

Another short & easy way:

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

Best and clean way.

Answer

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

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 );
} );
Answer

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());
});
Answer

Try this:

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

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

});

http://jsfiddle.net/mTGhV/

Answer

How about this?

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

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.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.