Utilizzo di jQuery per sostituire un tag con un altro


100

Obbiettivo:

Utilizzando jQuery, sto cercando di sostituire tutte le occorrenze di:

<code> ... </code>

con:

<pre> ... </pre>

La mia soluzione:

Sono arrivato fino a quanto segue,

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

Il problema con la mia soluzione:

ma il problema è che sta sostituendo tutto ciò che si trova tra i tag "code" (secondo, terzo, quarto, ecc.) con il contenuto tra i primi tag "code".

per esempio

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

diventa

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

Penso di aver bisogno di usare "questo" e una sorta di funzione, ma temo che sto ancora imparando e non capisco davvero come mettere insieme una soluzione.


Risolto il problema con la soluzione wrap-unfrap ora jon - dai un'occhiata;)
Jens Roland

Risposte:


157

Puoi passare una funzione a .replaceWith [docs] :

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

All'interno della funzione, thisfa riferimento codeall'elemento attualmente elaborato .

DEMO

Aggiornamento: non c'è una grande differenza di prestazioni , ma nel caso in cui gli codeelementi abbiano altri figli HTML, aggiungere i figli invece di serializzarli sembra essere più corretto:

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

1
questa sembra essere la soluzione più elegante, anche se devo ammettere che non capisco cosa sta succedendo all'interno della funzione replaceWith. mi piacerebbe saperne di più. cioè come è l'assegnazione dei tag di apertura e chiusura? lo spazio in <pre /> lo fa?
jon

2
@jon: è una mano breve per creare nuovi elementi. Ulteriori informazioni sono disponibili qui: api.jquery.com/jQuery/#jQuery2 . jQuery esegue il ciclo su tutti gli elementi ed esegue la funzione per ciascuno di essi (lo stesso che .eachsta facendo).
Felix Kling

@jon: Ma controlla di nuovo la soluzione di Jens, l'ha riparata.
Felix Kling

1
+1 per un bel trucco - questo può essere usato per molto di più che una semplice sostituzione tag per tag.
Jens Roland

@FelixKling Questo non sovrascriverebbe gli attributi dei tag di codice?
tewathia

80

Questo è molto più carino:

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

Anche se è vero che la soluzione di Felix Kling è circa il doppio più veloce :


4
ha funzionato a meraviglia, ai miei occhi laici questa sembra essere la soluzione più efficace. :)
jon

aha. sì, ragazzi avevate ragione. non ha funzionato neanche per me. grazie per averlo notato!
jon

1
FWIW, $('code').children()restituirà un oggetto jQuery vuoto per l'esempio precedente, perché gli codeelementi non hanno nodi elemento figlio. Anche se funziona se ci sono elementi figlio.
Felix Kling

1
Risolto - vero, quando il contenuto è costituito da un singolo nodo di testo, children()non funzionerà. L'utilizzo contents()invece funziona perfettamente. jsfiddle.net/7Yne9
Jens Roland

1
Ecco una versione jsperf che non rompe la pagina: jsperf.com/substituting-one-tag-for-another-with-jquery/2 e vedi che la differenza di velocità non è più così grande. La tua soluzione è più lenta perché esegui due manipolazioni DOM per elemento: unwraprimuove il genitore e aggiunge i figli all'albero, wrapli scollega di nuovo e aggiunge un nuovo genitore.
Felix Kling

26

È corretto che otterrai sempre il codecontenuto del primo , perché $('code').html()farà sempre riferimento al primo elemento, ovunque tu lo usi.

Invece, potresti usare .eachper iterare su tutti gli elementi e cambiarli individualmente:

$('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

Prova questo:

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

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

});

http://jsfiddle.net/mTGhV/


Wow. voi ragazzi avete trovato la stessa identica soluzione entro 2 secondi l'uno dall'altro. ci sono piccole differenze di formattazione. Non sono sicuro di quale votare - Non mi piace davvero lo spazio tra la funzione e () nella risposta di thomas e le 2 linee di spazio vuoto nella risposta kokos sono piuttosto puntuali + dovrebbe esserci uno spazio tra il () e il {
Michael Bylstra

11

Cosa ne pensi di questo?

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

6

Basandosi sulla risposta di 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;
});

Ciò riprodurrà gli attributi dei codetag nei pretag sostitutivi .

Modifica: sostituirà anche quei codetag che si trovano all'interno innerHTMLdi altri codetag.

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
la migliore risposta finora. Gli altri sono praticamente tutti uguali, il che è davvero strano che le persone li apprezzino. Congratulazioni per essere l'unico che ha pensato agli attributi.
Guilherme David da Costa


2

Se stessi utilizzando JavaScript vanilla, dovresti:

  • Crea il nuovo elemento
  • Sposta i figli del vecchio elemento nel nuovo elemento
  • Inserisci il nuovo elemento prima di quello vecchio
  • Rimuovi il vecchio elemento

Ecco l'equivalente jQuery di questo processo:

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

Ecco l'URL jsperf:
http://jsperf.com/substituting-one-tag-for-another-with-jquery/7

PS: tutte le soluzioni che utilizzano .html()o .innerHTMLsono distruttive .



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

Modo migliore e pulito.


0

Potresti usare la funzione html di jQuery. Di seguito è riportato un esempio che sostituisce un tag di codice con un tag pre conservando tutti gli attributi del codice.

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

Questo potrebbe funzionare con qualsiasi set di tag elemento html che necessitava di essere scambiato mantenendo tutti gli attributi del tag precedente.


0

jqueryPlugin realizzato , mantenendo anche gli attributi.

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

Uso:

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

0

Tutte le risposte fornite qui presuppongono (come indica l'esempio della domanda) che non ci siano attributi nel tag. Se la risposta accettata viene eseguita su questo:

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

se verrà sostituito con

<pre>A</pre>

E se volessi mantenere anche gli attributi, cosa significherebbe sostituire un tag ...? Questa è la soluzione:

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

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

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

So che è vecchio di un paio di anni ma ho pensato di menzionare ... ti sei dimenticato di mantenere l'html dell'elemento precedente. Nel tuo frammento di codice stai solo creando un nuovo elemento con gli attributi senza copiare anche nessuno dei bambini.
Un amico

ciò sarebbe fatto aggiungendocontent.html( this.html )
patrick
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.