Utilizzare jQuery per modificare un tag HTML?


130

È possibile?

esempio:

$('a.change').click(function(){
//code to change p tag to h5 tag
});


<p>Hello!</p>
<a id="change">change</a>

Pertanto, facendo clic sull'ancoraggio di modifica, la <p>Hello!</p>sezione dovrebbe cambiare (ad esempio) un tag h5 in modo da finire <h5>Hello!</h5>dopo il clic. Mi rendo conto che puoi eliminare il tag p e sostituirlo con un h5, ma esiste comunque un modo per modificare effettivamente un tag HTML?

Risposte:


211

Una volta creato un elemento dom, credo che il tag sia immutabile. Dovresti fare qualcosa del genere:

$(this).replaceWith($('<h5>' + this.innerHTML + '</h5>'));

2
Si prega di vedere il mio commento qui sotto ... cambiare la struttura del documento per applicare lo stile non è l'approccio migliore.
jrista,

39
Questo clobber non avrebbe qualche attributo che potrebbe essere sull'elemento che hai sostituito? Potrebbe comportare un comportamento imprevisto a causa di attributi di stile, attributi di dati, ecc.
Eliminati

5
"<" + el.outerHTML.replace(/(^<\w+|\w+>$)/g, "H5") + ">";O funzione jQuery collegabile: link
basil

65

Ecco un'estensione che farà tutto, su tanti elementi in tanti modi ...

Esempio di utilizzo:

mantenere la classe e gli attributi esistenti:

$('div#change').replaceTag('<span>', true);

o

Elimina classe e attributi esistenti:

$('div#change').replaceTag('<span class=newclass>', false);

o anche

sostituisci tutti i div con span, copia classi e attributi, aggiungi un nome di classe extra

$('div').replaceTag($('<span>').addClass('wasDiv'), true);

Fonte del plugin:

$.extend({
    replaceTag: function (currentElem, newTagObj, keepProps) {
        var $currentElem = $(currentElem);
        var i, $newTag = $(newTagObj).clone();
        if (keepProps) {//{{{
            newTag = $newTag[0];
            newTag.className = currentElem.className;
            $.extend(newTag.classList, currentElem.classList);
            $.extend(newTag.attributes, currentElem.attributes);
        }//}}}
        $currentElem.wrapAll($newTag);
        $currentElem.contents().unwrap();
        // return node; (Error spotted by Frank van Luijn)
        return this; // Suggested by ColeLawrence
    }
});

$.fn.extend({
    replaceTag: function (newTagObj, keepProps) {
        // "return" suggested by ColeLawrence
        return this.each(function() {
            jQuery.replaceTag(this, newTagObj, keepProps);
        });
    }
});

2
Sì. E per la cronaca, ci sono in realtà molte ragioni molto valide che potresti voler cambiare un tag. ad esempio se avevi tag DIV all'interno di uno SPAN, che è hella non standard. Ho sfruttato molto questa funzione mentre lavoravo con i rigidi standard di princexml per la pubblicazione pdb.
Orwellophile,

1
Sembra davvero bello, anche se sfortunatamente perde tutti gli eventi dell'elemento sostituito. Forse anche quello potrebbe essere gestito - sarebbe fantastico!
NPC il

@NPC è la vita nella grande città. se hai intenzione di sostituire elementi, ci saranno vittime. sono sicuro che c'è qualcuno là fuori che conosce il jquery rilevante per clonare gli eventi :)
Orwellophile,

1
@FrankvanLuijn @orwellophile return node;dovrebbe effettivamente essere return this;come mostrato nella "vecchia versione" del plugin. Questo è essenziale per concatenare eventi come$("tr:first").find("td").clone().replaceTag("li").appendTo("ul#list")
Cole Lawrence,

1
Non capisco, perché hai bisogno di 2 funzioni? Hai bisogno di entrambi? Scusa, mi sono perso
João Pimentel Ferreira,

12

Invece di cambiare il tipo di tag, dovresti cambiare lo stile del tag (o meglio, il tag con un ID specifico). Non è una buona pratica cambiare gli elementi del tuo documento per applicare cambiamenti stilistici. Prova questo:

$('a.change').click(function() {
    $('p#changed').css("font-weight", "bold");
});

<p id="changed">Hello!</p>
<a id="change">change</a>

3
Anche in questo caso, non dovresti modificare la struttura del documento. Se è necessario visualizzare un input in risposta a un clic di modifica, fare clic sull'input e incollare display: nessuno o visibilità: nascosto su di esso. Nascondi <h5> e mostra <input> in risposta al clic sul pulsante. Se stai modificando costantemente la struttura del tuo documento ... stai solo chiedendo un sacco di problemi di stile e layout lungo la strada.
jrista,

1
Assolutamente. Il tuo javascript è incorporato o collegato, quindi se la tua preoccupazione è la sicurezza, il tuo approccio alla sicurezza è in qualche modo imperfetto. Dovresti rendere il contenuto del tuo documento in base al ruolo dell'utente ... la fusione del contenuto per i ruoli non è un modo sicuro per affrontare il problema. Se qualcuno è connesso al tuo sistema come amministratore, esegui il rendering del contenuto per un amministratore. Se sono connessi al tuo sistema come lettore, esegui il rendering del contenuto per un lettore. Questo elimina completamente il contenuto a cui non si dovrebbe accedere. Una volta eseguito il rendering del contenuto, utilizzare i CSS per modellare il documento e mostrare / nascondere elementi.
jrista,

2
Sono d'accordo con te e ho preso le tue raccomandazioni nel progetto. Userò toggle () per mostrare gli elementi admin che sono rappresentati solo quando un admin è loggato. Sebbene non sia correlato (direttamente) alla domanda originale, questa è probabilmente una soluzione migliore della direzione in cui stavo andando originariamente. Saluti!
Christopher Cooper,

1
Corteggiare! Ho insaccato un altro blocco di cattiva sicurezza! Una vittoria e round per tutti! (inserisci qui l'icona della birra)
jrista

1
Affidarsi al javascript sul lato client per la sicurezza è in realtà PEGGIORE di nessuna sicurezza. Perché? Perché pensi di avere sicurezza, mentre in realtà non lo fai.
BryanH,

8

Ho notato che la prima risposta non era proprio ciò di cui avevo bisogno, quindi ho apportato un paio di modifiche e ho pensato di postarla di nuovo qui.

migliorata replaceTag(<tagName>)

replaceTag(<tagName>, [withDataAndEvents], [withDataAndEvents])

Argomenti:

  • tagName: String
    • Il nome del tag, ad esempio "div", "span", ecc.
  • withDataAndEvents: Boolean
    • "Un valore booleano che indica se i gestori di eventi devono essere copiati insieme agli elementi. A partire da jQuery 1.4, verranno copiati anche i dati degli elementi." Informazioni
  • deepWithDataAndEvents: Boolean ,
    • Un valore booleano che indica se i gestori di eventi e i dati per tutti i figli dell'elemento clonato devono essere copiati. Per impostazione predefinita, il suo valore corrisponde al valore del primo argomento (che per impostazione predefinita è false). " Info

Ritorna:

Un elemento jQuery appena creato

Ok, so che ci sono alcune risposte qui ora, ma mi sono preso la responsabilità di scriverlo di nuovo.

Qui possiamo sostituire il tag nello stesso modo in cui utilizziamo la clonazione. Stiamo seguendo la stessa sintassi di .clone () con withDataAndEventse deepWithDataAndEventsche copia il figlio dati e gli eventi dei nodi se utilizzati.

Esempio:

$tableRow.find("td").each(function() {
  $(this).clone().replaceTag("li").appendTo("ul#table-row-as-list");
});

Fonte:

$.extend({
    replaceTag: function (element, tagName, withDataAndEvents, deepWithDataAndEvents) {
        var newTag = $("<" + tagName + ">")[0];
        // From [Stackoverflow: Copy all Attributes](http://stackoverflow.com/a/6753486/2096729)
        $.each(element.attributes, function() {
            newTag.setAttribute(this.name, this.value);
        });
        $(element).children().clone(withDataAndEvents, deepWithDataAndEvents).appendTo(newTag);
        return newTag;
    }
})
$.fn.extend({
    replaceTag: function (tagName, withDataAndEvents, deepWithDataAndEvents) {
        // Use map to reconstruct the selector with newly created elements
        return this.map(function() {
            return jQuery.replaceTag(this, tagName, withDataAndEvents, deepWithDataAndEvents);
        })
    }
})

Nota che questo non sostituisce l'elemento selezionato, restituisce quello appena creato.


2
Tenere presente che .children()non includerà nodi puramente testuali. Potresti provare .contents()IIRC.
Orwellophile,

5

L'idea è di avvolgere l'elemento e scartare il contenuto:

function renameElement($element,newElement){

    $element.wrap("<"+newElement+">");
    $newElement = $element.parent();

    //Copying Attributes
    $.each($element.prop('attributes'), function() {
        $newElement.attr(this.name,this.value);
    });

    $element.contents().unwrap();       

    return $newElement;
}

Esempio di utilizzo:

renameElement($('p'),'h5');

dimostrazione


0

Ho trovato un approccio in cui usi una rappresentazione in forma di stringa del tuo oggetto jQuery e sostituisci il nome del tag usando espressioni regolari e JavaScript di base. Non perderai alcun contenuto e non dovrai scorrere su ogni attributo / proprietà.

/*
 * replaceTag
 * @return {$object} a new object with replaced opening and closing tag
 */
function replaceTag($element, newTagName) {

  // Identify opening and closing tag
  var oldTagName = $element[0].nodeName,
    elementString = $element[0].outerHTML,
    openingRegex = new RegExp("^(<" + oldTagName + " )", "i"),
    openingTag = elementString.match(openingRegex),
    closingRegex = new RegExp("(<\/" + oldTagName + ">)$", "i"),
    closingTag = elementString.match(closingRegex);

  if (openingTag && closingTag && newTagName) {
    // Remove opening tag
    elementString = elementString.slice(openingTag[0].length);
    // Remove closing tag
    elementString = elementString.slice(0, -(closingTag[0].length));
    // Add new tags
    elementString = "<" + newTagName + " " + elementString + "</" + newTagName + ">";
  }

  return $(elementString);
}

Infine, puoi sostituire l'oggetto / nodo esistente come segue:

var $newElement = replaceTag($rankingSubmit, 'a');
$('#not-an-a-element').replaceWith($newElement);

0

Questa è la mia soluzione Permette di alternare tra i tag.

<!DOCTYPE html>
<html>
<head>
	<title></title>

<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script type="text/javascript">

function wrapClass(klass){
	return 'to-' + klass;
}

function replaceTag(fromTag, toTag){
	
	/** Create selector for all elements you want to change.
	  * These should be in form: <fromTag class="to-toTag"></fromTag>
	  */
	var currentSelector = fromTag + '.' + wrapClass(toTag);

	/** Select all elements */
	var $selected = $(currentSelector);

	/** If you found something then do the magic. */
	if($selected.size() > 0){

		/** Replace all selected elements */
		$selected.each(function(){

			/** jQuery current element. */
			var $this = $(this);

			/** Remove class "to-toTag". It is no longer needed. */
			$this.removeClass(wrapClass(toTag));

			/** Create elements that will be places instead of current one. */
			var $newElem = $('<' + toTag + '>');

			/** Copy all attributes from old element to new one. */
			var attributes = $this.prop("attributes");
			$.each(attributes, function(){
				$newElem.attr(this.name, this.value);
			});

			/** Add class "to-fromTag" so you can remember it. */
			$newElem.addClass(wrapClass(fromTag));

			/** Place content of current element to new element. */
			$newElem.html($this.html());

			/** Replace old with new. */
			$this.replaceWith($newElem);
		});

		/** It is possible that current element has desired elements inside.
		  * If so you need to look again for them.
		  */
		replaceTag(fromTag, toTag);
	}
}


</script>

<style type="text/css">
	
	section {
		background-color: yellow;
	}

	div {
		background-color: red;
	}

	.big {
		font-size: 40px;
	}

</style>
</head>
<body>

<button onclick="replaceTag('div', 'section');">Section -> Div</button>
<button onclick="replaceTag('section', 'div');">Div -> Section</button>

<div class="to-section">
	<p>Matrix has you!</p>
	<div class="to-section big">
		<p>Matrix has you inside!</p>
	</div>
</div>

<div class="to-section big">
	<p>Matrix has me too!</p>
</div>

</body>
</html>


0

Questo è il modo rapido per cambiare i tag HTML all'interno del DOM usando jQuery. Trovo che questa funzione replWith () sia molto utile.

   var text= $('p').text();
   $('#change').on('click', function() {
     target.replaceWith( "<h5>"+text+"</h5>" );
   });

0

Puoi ottenere in base data-*all'attributo in questo data-replace="replaceTarget,replaceBy"modo con l'aiuto di jQuery per ottenere replaceTargete replaceByvalutare per .split()metodo dopo aver ottenuto i valori, quindi usa il .replaceWith()metodo.
Questa data-*tecnica di attributo consente di gestire facilmente qualsiasi sostituzione di tag senza cambiare di seguito (codice comune per la sostituzione di tutti i tag).

Spero che lo snippet di seguito ti possa aiutare molto.

$(document).on('click', '[data-replace]', function(){
  var replaceTarget = $(this).attr('data-replace').split(',')[0];
  var replaceBy = $(this).attr('data-replace').split(',')[1];
  $(replaceTarget).replaceWith($(replaceBy).html($(replaceTarget).html()));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<p id="abc">Hello World #1</p>
<a href="#" data-replace="#abc,<h1/>">P change with H1 tag</a>
<hr>
<h2 id="xyz">Hello World #2</h2>
<a href="#" data-replace="#xyz,<p/>">H1 change with P tag</a>
<hr>
<b id="bold">Hello World #2</b><br>
<a href="#" data-replace="#bold,<i/>">B change with I tag</a>
<hr>
<i id="italic">Hello World #2</i><br>
<a href="#" data-replace="#italic,<b/>">I change with B tag</a>


0

La seguente funzione fa il trucco e mantiene tutti gli attributi. Lo usi ad esempio in questo modo:changeTag("div", "p")

function changeTag(originTag, destTag) {
  while($(originTag).length) {
    $(originTag).replaceWith (function () {
      var attributes = $(this).prop("attributes");
      var $newEl = $(`<${destTag}>`)
      $.each(attributes, function() {
        $newEl.attr(this.name, this.value);
      });  
      return $newEl.html($(this).html())
    })
  }
}

Per essere sicuro che funzioni, controlla il seguente esempio

function changeTag(originTag, destTag) {
  while($(originTag).length) {
    $(originTag).replaceWith (function () {
      var attributes = $(this).prop("attributes");
      var $newEl = $(`<${destTag}>`)
      $.each(attributes, function() {
        $newEl.attr(this.name, this.value);
      });  
      return $newEl.html($(this).html())
    })
  }
}

changeTag("div", "p")

console.log($("body").html())
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="A" style="font-size:1em">
  <div class="B" style="font-size:1.1em">A</div>
</div>
<div class="C" style="font-size:1.2em">
  B
</div>
</body>


-1

C'è un motivo specifico per cui è necessario modificare il tag? Se vuoi solo ingrandire il testo, cambiare la classe CSS del tag p sarebbe un modo migliore per farlo.

Qualcosa come questo:

$('#change').click(function(){
  $('p').addClass('emphasis');
});

Il motivo per cui sto chiedendo di cambiare l'elemento / tag è perché sto provando a cambiare un tag (un <h5>, sebbene il tipo sia irrilevante) in un <input> quando si fa clic su un pulsante "modifica" altrove nella pagina .
Christopher Cooper,
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.