Gunakan jQuery untuk mengubah tag HTML?

130

Apakah ini mungkin?

contoh:

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


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

Jadi mengklik jangkar perubahan harus menyebabkan <p>Hello!</p>bagian berubah menjadi (sebagai contoh) tag h5 sehingga Anda akan berakhir dengan <h5>Hello!</h5>setelah klik. Saya sadar Anda dapat menghapus tag p dan menggantinya dengan h5, tetapi adakah yang benar-benar memodifikasi tag HTML?

Christopher Cooper
sumber

Jawaban:

211

Setelah elemen dom dibuat, tag tidak berubah, saya percaya. Anda harus melakukan sesuatu seperti ini:

$(this).replaceWith($('<h5>' + this.innerHTML + '</h5>'));
mishac
sumber
2
Silakan lihat komentar saya di bawah ini ... mengubah struktur dokumen untuk menerapkan gaya bukan pendekatan terbaik.
jrista
39
Bukankah clobber ini atribut yang mungkin ada pada elemen yang Anda ganti? Dapat menyebabkan beberapa perilaku tak terduga karena atribut gaya yang dihapus, atribut data, dll ...
Xavi
5
"<" + el.outerHTML.replace(/(^<\w+|\w+>$)/g, "H5") + ">";Atau fungsi jQuery pluggable: link
basil
65

Berikut ini adalah ekstensi yang akan melakukan semuanya, pada banyak elemen dalam banyak cara ...

Contoh penggunaan:

menjaga kelas dan atribut yang ada:

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

atau

Buang kelas dan atribut yang ada:

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

atau bahkan

ganti semua div dengan rentang, salin kelas dan atribut, tambahkan nama kelas tambahan

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

Sumber 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);
        });
    }
});
Orwellophile
sumber
2
Ya. Dan sebagai catatan, sebenarnya ada banyak alasan yang sangat valid Anda mungkin ingin mengubah tag. mis. jika Anda memiliki tag DIV dalam SPAN, yang hella non-standar. Saya mendapatkan banyak kegunaan dari fungsi ini saat bekerja dengan standar ketat princexml untuk penerbitan pdb.
Orwellophile
1
Terlihat sangat bagus, meskipun sayangnya kehilangan semua peristiwa dari elemen yang diganti. Mungkin itu bisa ditangani juga - akan luar biasa!
NPC
@NPC itulah kehidupan di kota besar. jika Anda akan mengganti elemen, akan ada korban jiwa. Saya yakin ada seseorang di luar sana yang tahu jquery yang relevan untuk mengkloning acara :)
Orwellophile
1
@FrankvanLuijn @orwellophile return node;seharusnya benar-benar return this;seperti yang ditunjukkan dalam "versi lama" dari plugin. Ini penting untuk merantai acara bersama seperti$("tr:first").find("td").clone().replaceTag("li").appendTo("ul#list")
Cole Lawrence
1
Saya tidak mengerti, mengapa Anda perlu 2 fungsi? Apakah Anda membutuhkan keduanya? Maaf, saya tersesat
João Pimentel Ferreira
12

Daripada mengubah jenis tag, Anda harus mengubah gaya tag (atau lebih tepatnya, tag dengan id tertentu). Ini bukan praktik yang baik untuk mengubah elemen dokumen Anda untuk menerapkan perubahan gaya. Coba ini:

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

<p id="changed">Hello!</p>
<a id="change">change</a>
jrista
sumber
3
Bahkan dalam kasus ini, Anda tidak boleh memodifikasi struktur dokumen Anda. Jika Anda perlu menampilkan input sebagai respons terhadap suntikan yang sedang diklik, maka masukkan input dan tempelkan tampilan: tidak ada atau visibilitas: disembunyikan di dalamnya. Sembunyikan <h5> dan tunjukkan <input> sebagai respons terhadap klik tombol. Jika Anda terus-menerus mengubah struktur dokumen Anda ... Anda hanya meminta seember penuh masalah gaya dan tata letak.
jrista
1
Benar. Javascript Anda tertanam atau ditautkan, jadi jika kekhawatiran Anda adalah keamanan, maka pendekatan Anda terhadap keamanan agak cacat. Anda harus merender konten dokumen Anda sesuai dengan peran pengguna ... memadukan konten untuk peran bukanlah cara yang aman untuk mendekati masalah. Jika seseorang masuk ke sistem Anda sebagai admin, render konten untuk admin. Jika mereka masuk ke sistem Anda sebagai pembaca, render konten untuk pembaca. Ini sepenuhnya menghilangkan konten yang tidak boleh diakses. Setelah konten diberikan, gunakan CSS untuk menata dokumen Anda dan menampilkan / menyembunyikan barang.
jrista
2
Saya setuju dengan Anda dan telah mengambil rekomendasi Anda ke dalam proyek. Saya akan menggunakan toggle () untuk menampilkan elemen admin yang hanya dirender ketika admin masuk. Meskipun tidak terkait (langsung) dengan pertanyaan awal, ini mungkin solusi yang lebih baik daripada arah yang semula saya tuju. Bersulang!
Christopher Cooper
1
Merayu! Mengantongi sekumpulan keamanan buruk lainnya! Kemenangan, dan ronde untuk semua! (masukkan ikon bir di sini)
jrista
1
Mengandalkan javascript sisi klien untuk keamanan sebenarnya lebih buruk daripada tidak ada keamanan sama sekali. Mengapa? Karena Anda pikir Anda memiliki keamanan, padahal sebenarnya tidak.
BryanH
8

Saya perhatikan bahwa jawaban pertama bukanlah yang saya butuhkan, jadi saya membuat beberapa modifikasi dan berpikir saya akan mempostingnya kembali ke sini.

Ditingkatkan replaceTag(<tagName>)

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

Argumen:

  • tagName: String
    • Nama tag misalnya "div", "span", dll.
  • withDataAndEvents: Boolean
    • "Boolean yang menunjukkan apakah event handler harus disalin bersama dengan elemen. Pada jQuery 1.4, data elemen akan disalin juga." info
  • deepWithDataAndEvents: Boolean ,
    • Boolean yang menunjukkan apakah event handler dan data untuk semua anak dari elemen yang dikloning harus disalin. Secara default nilainya sesuai dengan nilai argumen pertama (yang default ke false)." Info

Pengembalian:

Elemen jQuery yang baru dibuat

Oke, saya tahu ada beberapa jawaban di sini sekarang, tetapi saya mengambil sendiri untuk menulis ini lagi.

Di sini kita dapat mengganti tag dengan cara yang sama seperti kita menggunakan kloning. Kami mengikuti sintaksis yang sama dengan .clone () dengan withDataAndEventsdan deepWithDataAndEventsyang menyalin data dan kejadian node anak jika digunakan.

Contoh:

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

Sumber:

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

Perhatikan bahwa ini tidak menggantikan elemen yang dipilih, ini mengembalikan elemen yang baru dibuat.

Cole Lawrence
sumber
2
Sadarilah bahwa .children()tidak akan menyertakan node teks murni. Anda mungkin ingin mencoba .contents()IIRC.
Orwellophile
5

Ide adalah membungkus elemen & membuka isinya:

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

Penggunaan sampel:

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

Demo

Shubanker
sumber
0

Saya datang dengan pendekatan di mana Anda menggunakan representasi string dari objek jQuery Anda dan mengganti nama tag menggunakan ekspresi reguler dan JavaScript dasar. Anda tidak akan kehilangan konten apa pun dan tidak perlu mengulang setiap atribut / properti.

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

Akhirnya, Anda dapat mengganti objek / simpul yang ada sebagai berikut:

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

Ini solusi saya. Memungkinkan untuk beralih di antara 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>

zie1ony
sumber
0

Ini cara cepat untuk mengubah tag HTML di dalam DOM Anda menggunakan jQuery. Saya menemukan fungsi replaceWith () ini sangat berguna.

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

Anda dapat mencapai dengan data-*atribut seperti data-replace="replaceTarget,replaceBy"itu dengan bantuan jQuery untuk mendapatkan replaceTarget& replaceBynilai dengan .split()metode setelah mendapatkan nilai kemudian gunakan .replaceWith()metode. Teknik atribut
ini data-*untuk mengelola penggantian tag dengan mudah tanpa mengubah di bawah (kode umum untuk semua penggantian tag).

Saya harap cuplikan di bawah ini akan banyak membantu Anda.

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

Raeesh Alam
sumber
0

Fungsi berikut melakukan trik dan menyimpan semua atribut. Anda menggunakannya misalnya seperti ini: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())
    })
  }
}

Untuk memastikan itu berfungsi, periksa contoh berikut

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>

João Pimentel Ferreira
sumber
-1

Apakah ada alasan khusus bahwa Anda perlu mengubah tag? Jika Anda hanya ingin membuat teks lebih besar, mengubah kelas CSS tag p akan menjadi cara yang lebih baik untuk melakukannya.

Sesuatu seperti ini:

$('#change').click(function(){
  $('p').addClass('emphasis');
});
Dave Ward
sumber
Alasan saya meminta untuk mengubah elemen / tag adalah karena saya mencoba untuk mengubah tag (sebuah <h5>, meskipun jenisnya tidak relevan) menjadi <input> ketika tombol "edit" diklik di tempat lain pada halaman .
Christopher Cooper