admin管理员组

文章数量:1131257

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.

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.

Share Improve this question edited Aug 22, 2017 at 20:13 ROMANIA_engineer 56.5k30 gold badges208 silver badges205 bronze badges asked Aug 17, 2011 at 13:10 jonjon 6,2218 gold badges37 silver badges43 bronze badges 1
  • Fixed the wrap-unwrap solution now jon - check it out ;) – Jens Roland Commented Aug 17, 2011 at 13:34
Add a comment  | 

13 Answers 13

Reset to default 176

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

This is much nicer:

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

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

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

Try this:

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

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

});

http://jsfiddle.net/mTGhV/

How about this?

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

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

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/

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.

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

Another short & easy way:

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

Best and clean way.

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.

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

本文标签: javascriptUsing jQuery to replace one tag with anotherStack Overflow