Menggunakan jQuery untuk mengganti satu tag dengan yang lain

101

Tujuan:

Menggunakan jQuery, saya mencoba mengganti semua kemunculan:

<code> ... </code>

dengan:

<pre> ... </pre>

Solusi saya:

Saya sampai pada yang berikut,

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

Masalah dengan solusi saya:

tetapi masalahnya adalah ia mengganti semua yang ada di antara tag "kode" (kedua, ketiga, keempat, dll.) dengan konten di antara tag "kode" pertama .

misalnya

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

menjadi

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

Saya rasa saya perlu menggunakan "ini" dan semacam fungsi, tetapi saya khawatir saya masih belajar dan tidak benar-benar memahami cara menyusun solusi bersama.

jon
sumber
Memperbaiki solusi bungkus-buka sekarang jon - periksa;)
Jens Roland

Jawaban:

157

Anda dapat meneruskan fungsi ke .replaceWith [docs] :

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

Di dalam fungsi, thismengacu pada codeelemen yang sedang diproses .

DEMO

Pembaruan: Tidak ada perbedaan performa yang besar , tetapi jika codeelemen memiliki turunan HTML lain, menambahkan turunan alih-alih membuat serialisasi dirasa lebih tepat:

$('code').replaceWith(function(){
    return $("<pre />").append($(this).contents());
});
Felix Kling
sumber
1
ini tampaknya menjadi solusi yang paling elegan, saya akui saya tidak mengerti apa yang terjadi di dalam fungsi replaceWith. ingin mendengar lebih banyak. yaitu, bagaimana menetapkan tag pembuka DAN penutup? apakah ruang di <pre /> mencapai itu?
jon
2
@jon: Ini adalah cara singkat untuk membuat elemen baru. Informasi lebih lanjut dapat ditemukan di sini: api.jquery.com/jQuery/#jQuery2 . jQuery mengulang semua elemen dan menjalankan fungsi untuk masing-masing elemen (sama seperti .eachyang dilakukan).
Felix Kling
@ Jon: Tapi periksa lagi solusi Jens, dia memperbaikinya.
Felix Kling
1
+1 untuk trik yang bagus - ini dapat digunakan untuk lebih dari sekadar substitusi tag-untuk-tag.
Jens Roland
@FelixKling Bukankah ini menimpa atribut tag kode?
tewathia
80

Ini jauh lebih bagus:

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

Meskipun memang solusi Felix Kling kira-kira dua kali lebih cepat :

Jens Roland
sumber
4
bekerja seperti pesona, bagi mata saya ini tampaknya menjadi solusi yang paling efisien. :)
jon
aha. ya, kalian benar. itu juga tidak berhasil untuk saya. terima kasih sudah menangkapnya!
jon
1
FWIW, $('code').children()akan mengembalikan objek jQuery kosong untuk contoh di atas, karena codeelemen tidak memiliki node elemen anak. Padahal itu berhasil jika ada elemen anak.
Felix Kling
1
Fixed - true, ketika konten terdiri dari satu node teks, children()tidak akan berfungsi. Menggunakan contents()malah berfungsi dengan sempurna. jsfiddle.net/7Yne9
Jens Roland
1
Berikut adalah versi jsperf yang tidak merusak halaman: jsperf.com/substituting-one-tag-for-another-with-jquery/2 dan Anda melihat perbedaan kecepatan tidak terlalu besar lagi. Solusi Anda lebih lambat karena Anda melakukan dua manipulasi DOM per elemen: unwrapmenghapus induk dan menambahkan turunan ke pohon, wrapmelepaskannya lagi dan menambahkan induk baru.
Felix Kling
26

Benar bahwa Anda akan selalu mendapatkan konten pertama code, karena $('code').html()akan selalu mengacu pada elemen pertama, di mana pun Anda menggunakannya.

Sebaliknya, Anda dapat menggunakan .eachuntuk mengulang semua elemen dan mengubahnya satu per satu:

$('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.
});
pimvdb.dll
sumber
12

Coba ini:

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

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

});

http://jsfiddle.net/mTGhV/

Kokos
sumber
Wow. kalian menemukan solusi yang persis sama dalam waktu 2 detik satu sama lain. ada perbedaan format kecil. Saya tidak yakin mana yang akan di-upvote - Saya sangat tidak suka spasi antara fungsi dan () di jawaban thomas dan 2 baris spasi kosong di jawaban kokos cukup jelas + harus ada spasi di antara () dan {
Michael Bylstra
11

Bagaimana dengan ini?

$('code').each(function () {
    $(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );
});
Tae-Sung Shin
sumber
6

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

Ini akan mereproduksi atribut codetag dalam penggantinyapre tag .

Sunting: Ini akan menggantikan bahkan codetag yang ada di dalam tag innerHTMLlain code.

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');
tewathia
sumber
2
jawaban terbaik sejauh ini. Yang lainnya hampir semuanya sama dan sangat aneh bahwa orang-orang memilihnya. Selamat karena telah menjadi satu-satunya yang memikirkan atribut.
Guilherme David da Costa
2

Jika Anda menggunakan vanilla JavaScript, Anda akan:

  • Buat elemen baru
  • Pindahkan anak dari elemen lama ke elemen baru
  • Masukkan elemen baru sebelum yang lama
  • Hapus elemen lama

Berikut adalah jQuery yang setara dengan proses ini:

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

Ini adalah URL jsperf:
http://jsperf.com/substituting-one-tag-for-another-with-jquery/7

PS: Semua solusi yang digunakan .html()atau .innerHTMLyang merusak .

Salman A
sumber
2

Cara singkat & mudah lainnya:

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

Cara terbaik dan bersih.

Nimek
sumber
0

Anda bisa menggunakan fungsi html jQuery. Di bawah ini adalah contoh yang menggantikan tag kode dengan tag awal dengan tetap mempertahankan semua atribut kode.

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

Ini bisa bekerja dengan kumpulan tag elemen html apa pun yang perlu ditukar sambil mempertahankan semua atribut dari tag sebelumnya.

Arnab C.
sumber
0

Membuat jqueryplugin, juga memelihara atribut.

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

Pemakaian:

$('code').renameTag('pre')
JagsSparrow
sumber
0

Semua jawaban yang diberikan di sini mengasumsikan (seperti yang ditunjukkan contoh pertanyaan) bahwa tidak ada atribut di tag. Jika jawaban yang diterima dijalankan ini:

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

jika akan diganti dengan

<pre>A</pre>

Bagaimana jika Anda ingin mempertahankan atribut juga - yang artinya mengganti tag ...? Inilah solusinya:

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

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

    $( this ).replaceWith( content );
} );
patrick
sumber
Saya tahu ini berumur beberapa tahun tetapi saya hanya berpikir saya akan menyebutkan ... Anda lupa menyimpan html dari elemen sebelumnya. Dalam cuplikan kode Anda, Anda baru saja membuat elemen baru dengan atribut tanpa menyalin salah satu turunan juga.
Seorang Teman
itu akan dilakukan dengan menambahkancontent.html( this.html )
patrick