Sử dụng jQuery để thay thế một thẻ này bằng một thẻ khác


100

Mục tiêu:

Sử dụng jQuery, tôi đang cố gắng thay thế tất cả các lần xuất hiện của:

<code> ... </code>

với:

<pre> ... </pre>

Giải pháp của tôi:

Tôi đã đi xa như sau,

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

Vấn đề với giải pháp của tôi:

nhưng vấn đề là nó thay thế mọi thứ giữa các thẻ "mã" (thứ hai, thứ ba, thứ tư, v.v.) bằng nội dung giữa các thẻ "mã" đầu tiên .

ví dụ

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

trở thành

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

Tôi nghĩ rằng tôi cần phải sử dụng "this" và một số loại hàm nhưng tôi sợ rằng tôi vẫn đang học và không thực sự hiểu cách ghép một giải pháp với nhau.


Cố định các giải pháp bọc Unwrap tại jon - check it out;)
Jens Roland

Câu trả lời:


157

Bạn có thể chuyển một hàm vào .replaceWith [docs] :

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

Bên trong hàm, thisđề cập đến codephần tử hiện đang được xử lý .

BẢN GIỚI THIỆU

Cập nhật: Không có sự khác biệt lớn về hiệu suất , nhưng trong trường hợp các codephần tử có các phần tử HTML khác, việc nối các phần tử con thay vì nối tiếp chúng sẽ cảm thấy chính xác hơn:

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

1
Đây có vẻ là giải pháp thanh lịch nhất, tôi thừa nhận rằng tôi không hiểu điều gì đang xảy ra bên trong hàm ReplaceWith. rất thích nghe nhiều hơn. tức là làm thế nào là chỉ định các thẻ mở VÀ đóng? không gian trong <pre /> có thực hiện được điều đó không?
jon

2
@jon: Đó là một bàn tay ngắn để tạo ra các yếu tố mới. Bạn có thể tìm thêm thông tin tại đây: api.jquery.com/jQuery/#jQuery2 . jQuery lặp lại trên tất cả các phần tử và thực thi chức năng cho từng phần tử đó (giống như những gì .eachđang làm).
Felix Kling

@jon: Nhưng hãy kiểm tra lại giải pháp của Jens, anh ấy đã sửa nó.
Felix Kling

1
+1 cho một thủ thuật hay - điều này có thể được sử dụng cho nhiều thứ hơn là chỉ thay thế thẻ-cho-thẻ đơn giản.
Jens Roland

@FelixKling Điều này sẽ không ghi đè các thuộc tính của thẻ mã sao?
tewathia

80

Cái này đẹp hơn nhiều:

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

Mặc dù phải thừa nhận là giải pháp Felix Kling của xấp xỉ nhanh gấp hai lần :


4
hoạt động như một sự quyến rũ, đối với mắt tôi đây dường như là giải pháp hiệu quả nhất. :)
jon

aha. vâng, các bạn đã đúng. nó cũng không làm việc cho tôi. cảm ơn vì đã nắm bắt được điều đó!
jon

1
FWIW, $('code').children()sẽ trả về một đối tượng jQuery trống cho ví dụ trên, vì các codephần tử không có nút phần tử con. Mặc dù nó hoạt động nếu có các phần tử con.
Felix Kling

1
Đã sửa - true, khi nội dung bao gồm một nút văn bản, children()sẽ không hoạt động. Sử dụng contents()thay thế hoạt động hoàn hảo. jsfiddle.net/7Yne9
Jens Roland

1
Đây là phiên bản jsperf không phá vỡ trang: jsperf.com/substituting-one-tag-for-aosystem-with-jquery/2 và bạn thấy sự khác biệt về tốc độ không còn quá lớn nữa. Giải pháp của bạn chậm hơn vì bạn thực hiện hai thao tác DOM cho mỗi phần tử: unwrapxóa phần tử gốc và thêm phần tử con vào cây, wraptách chúng lại và thêm phần tử gốc mới.
Felix Kling

26

Đúng là bạn sẽ luôn nhận được codenội dung của $('code').html()phần tử đầu tiên , vì sẽ luôn tham chiếu đến phần tử đầu tiên, dù bạn sử dụng nó ở đâu.

Thay vào đó, bạn có thể sử dụng .eachđể lặp lại tất cả các phần tử và thay đổi từng phần tử riêng lẻ:

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

12

Thử cái này:

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

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

});

http://jsfiddle.net/mTGhV/


ồ. các bạn đã đưa ra cùng một giải pháp trong vòng 2 giây của nhau. có sự khác biệt nhỏ về định dạng. Tôi không chắc nên ủng hộ cái nào - Tôi thực sự không thích khoảng trắng giữa hàm và () trong câu trả lời của thomas và 2 dòng khoảng trống trong câu trả lời kokos khá là nhọn + nên có khoảng trắng giữa () và {
Michael Bylstra

11

Còn cái này thì sao?

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

6

Dựa trên câu trả lời của Felix.

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

Điều này sẽ tái tạo các thuộc tính của các codethẻ trong các prethẻ thay thế .

Chỉnh sửa: Điều này sẽ thay thế ngay cả những codethẻ nằm bên trong innerHTMLcác codethẻ khác .

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

2
câu trả lời tốt nhất cho đến nay. Những cái khác khá giống nhau, điều thực sự kỳ lạ khi mọi người ủng hộ chúng. Xin chúc mừng vì là người duy nhất nghĩ về các thuộc tính.
Guilherme David da Costa


2

Nếu bạn đang sử dụng JavaScript vani, bạn sẽ:

  • Tạo phần tử mới
  • Di chuyển phần tử con của phần tử cũ vào phần tử mới
  • Chèn phần tử mới trước phần tử cũ
  • Xóa phần tử cũ

Đây là jQuery tương đương với quá trình này:

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

Đây là URL jsperf:
http://jsperf.com/substituting-one-tag-for-aosystem-with-jquery/7

PS: Tất cả các giải pháp sử dụng .html()hoặc .innerHTMLphá hoại .



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

Cách tốt nhất và sạch sẽ.


0

Bạn có thể sử dụng hàm html của jQuery. Dưới đây là một mẫu thay thế thẻ mã bằng thẻ trước trong khi vẫn giữ lại tất cả các thuộc tính của mã.

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

Điều này có thể hoạt động với bất kỳ tập hợp thẻ phần tử html nào cần được hoán đổi trong khi vẫn giữ lại tất cả các thuộc tính của thẻ trước đó.


0

Đã tạo jqueryplugin, cũng duy trì các thuộc tính.

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

Sử dụng:

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

0

Tất cả các câu trả lời được đưa ra ở đây giả định (như ví dụ câu hỏi chỉ ra) rằng không có thuộc tính nào trong thẻ. Nếu câu trả lời được chấp nhận được chạy trên này:

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

nếu sẽ được thay thế bằng

<pre>A</pre>

Điều gì xảy ra nếu bạn muốn giữ lại các thuộc tính - việc thay thế một thẻ sẽ có nghĩa là gì ...? Đây là giải pháp:

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

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

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

Tôi biết đây là một vài năm tuổi nhưng tôi chỉ nghĩ rằng tôi sẽ đề cập đến ... bạn quên giữ html từ phần tử trước đó. Trong đoạn mã của mình, bạn chỉ đang tạo một phần tử mới với các thuộc tính mà không sao chép bất kỳ phần tử con nào.
Một người bạn

điều đó sẽ được thực hiện bằng cách thêmcontent.html( this.html )
Patrick
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.