ใช้ jQuery เพื่อเปลี่ยนแท็ก HTML หรือไม่


130

เป็นไปได้หรือไม่

ตัวอย่าง:

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


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

ดังนั้นการคลิกจุดยึดการเปลี่ยนแปลงควรทำให้<p>Hello!</p>ส่วนนั้นเปลี่ยนเป็น (ดังตัวอย่าง) แท็ก h5 ดังนั้นคุณจะได้รับ<h5>Hello!</h5>หลังจากคลิก ฉันรู้ว่าคุณสามารถลบแท็ก p และแทนที่ด้วย h5 ได้ แต่จะมีการแก้ไขแท็ก HTML หรือไม่?

คำตอบ:


211

ฉันเชื่อว่าเมื่อสร้างองค์ประกอบ dom แล้วแท็กจะไม่เปลี่ยนรูป คุณต้องทำสิ่งนี้:

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

2
โปรดดูความคิดเห็นของฉันด้านล่าง ... การเปลี่ยนโครงสร้างเอกสารเพื่อใช้รูปแบบไม่ใช่แนวทางที่ดีที่สุด
jrista

39
จะไม่ปิดบังคุณลักษณะใด ๆ ที่อาจอยู่ในองค์ประกอบที่คุณแทนที่? อาจนำไปสู่พฤติกรรมที่ไม่คาดคิดเนื่องจากแอตทริบิวต์รูปแบบที่ถูกลบคุณลักษณะข้อมูล ฯลฯ ...
Xavi

5
"<" + el.outerHTML.replace(/(^<\w+|\w+>$)/g, "H5") + ">";หรือฟังก์ชั่น jQuery pluggable: การเชื่อมโยง
โหระพา

65

นี่คือส่วนเสริมที่จะทำทุกอย่างในหลาย ๆ องค์ประกอบในหลาย ๆ ทาง ...

ตัวอย่างการใช้งาน:

เก็บคลาสและคุณสมบัติที่มีอยู่:

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

หรือ

ยกเลิกคลาสและคุณสมบัติที่มีอยู่:

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

หรือแม้กระทั่ง

แทนที่ div ทั้งหมดด้วย spans คัดลอกคลาสและแอตทริบิวต์เพิ่มชื่อคลาสพิเศษ

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

แหล่งที่มาของปลั๊กอิน:

$.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
ได้. และสำหรับบันทึกนี้มีเหตุผลที่ถูกต้องหลายประการที่คุณอาจต้องการเปลี่ยนแท็ก เช่นหากคุณมีแท็ก DIV ภายใน SPAN ซึ่งไม่เป็นไปตามมาตรฐาน ฉันได้ใช้ประโยชน์จากฟังก์ชันนี้เป็นจำนวนมากในขณะที่ทำงานกับมาตรฐานที่เข้มงวดของ princexml สำหรับการเผยแพร่ pdb
Orwellophile

1
ดูดีจริงๆแม้ว่าจะโชคร้าย แต่ก็สูญเสียทุกเหตุการณ์ขององค์ประกอบที่ถูกแทนที่ บางทีมันก็สามารถจัดการได้เช่นกัน - น่ากลัว!
NPC

@NPC นั่นคือชีวิตในเมืองใหญ่ หากคุณกำลังจะเปลี่ยนองค์ประกอบจะมีผู้เสียชีวิต ฉันแน่ใจว่ามีใครบางคนที่รู้ jquery ที่เกี่ยวข้องเพื่อโคลนเหตุการณ์ :)
Orwellophile

1
@FrankvanLuijn @orwellophile return node;ควรจะเป็นจริงreturn this;ตามที่แสดงในปลั๊กอิน "เวอร์ชันเก่า" นี่คือสาระสำคัญสำหรับการเชื่อมโยงเหตุการณ์เข้าด้วยกันเช่น$("tr:first").find("td").clone().replaceTag("li").appendTo("ul#list")
Cole Lawrence

1
ไม่เข้าใจทำไมต้องมี 2 ฟังก์ชัน คุณต้องการทั้งสองอย่างหรือไม่? ขออภัยฉันหลงทาง
João Pimentel Ferreira

12

แทนที่จะเปลี่ยนประเภทของแท็กคุณควรเปลี่ยนรูปแบบของแท็ก (หรือแท็กที่มีรหัสเฉพาะ) ไม่ใช่แนวทางปฏิบัติที่ดีในการเปลี่ยนองค์ประกอบของเอกสารของคุณเพื่อใช้การเปลี่ยนแปลงโวหาร ลองสิ่งนี้:

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

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

3
แม้ในกรณีนี้คุณไม่ควรแก้ไขโครงสร้างเอกสารของคุณ หากคุณต้องการแสดงอินพุตเพื่อตอบสนองต่อการแก้ไข แต่เมื่อถูกคลิกให้ใส่อินพุตและแสดงผลแบบแท่ง: ไม่มีหรือการมองเห็น: ซ่อนอยู่ ซ่อน <h5> และแสดง <input> เพื่อตอบสนองต่อการคลิกปุ่ม หากคุณกำลังปรับเปลี่ยนโครงสร้างเอกสารของคุณอยู่ตลอดเวลา ... คุณแค่ขอรูปแบบและการจัดวางที่เต็มไปด้วยปัญหาตามท้องถนน
jrista

1
อย่างแน่นอน จาวาสคริปต์ของคุณถูกฝังหรือเชื่อมโยงดังนั้นหากคุณกังวลเรื่องความปลอดภัยวิธีการรักษาความปลอดภัยของคุณก็มีข้อบกพร่องอยู่บ้าง คุณควรแสดงเนื้อหาในเอกสารของคุณตามบทบาทของผู้ใช้ ... การผสมผสานเนื้อหาสำหรับบทบาทไม่ใช่วิธีที่ปลอดภัยในการแก้ไขปัญหา หากมีผู้เข้าสู่ระบบของคุณในฐานะผู้ดูแลระบบให้แสดงเนื้อหาสำหรับผู้ดูแลระบบ หากพวกเขาเข้าสู่ระบบของคุณในฐานะผู้อ่านให้แสดงเนื้อหาสำหรับผู้อ่าน สิ่งนี้จะกำจัดเนื้อหาที่ไม่ควรเข้าถึงโดยสิ้นเชิง เมื่อแสดงเนื้อหาแล้วให้ใช้ CSS เพื่อจัดรูปแบบเอกสารของคุณและแสดง / ซ่อนสิ่งต่างๆ
jrista

2
ฉันเห็นด้วยกับคุณและได้นำคำแนะนำของคุณไปใช้ในโครงการ ฉันจะใช้ toggle () เพื่อแสดงองค์ประกอบของผู้ดูแลระบบที่จะแสดงผลเมื่อผู้ดูแลระบบเข้าสู่ระบบเท่านั้นแม้ว่าจะไม่เกี่ยวข้อง (โดยตรง) กับคำถามเดิม แต่นี่อาจเป็นทางออกที่ดีกว่าแนวทางที่ฉันเคยไป ไชโย!
Christopher Cooper

1
แอ่ว! ถุงความปลอดภัยห่วยแตกอีก! ชนะและรอบสำหรับทุกคน! (ใส่ไอคอนเบียร์ที่นี่)
jrista

1
การใช้ javascript ฝั่งไคลเอ็นต์เพื่อความปลอดภัยนั้นแย่กว่าไม่มีความปลอดภัยเลย ทำไม? เพราะคุณคิดว่าคุณมีความปลอดภัย แต่ในความเป็นจริงคุณไม่มี
BryanH

8

ฉันสังเกตว่าคำตอบแรกไม่ตรงกับที่ฉันต้องการดังนั้นฉันจึงทำการปรับเปลี่ยนสองสามอย่างและคิดว่าฉันจะโพสต์กลับที่นี่

ปรับปรุง replaceTag(<tagName>)

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

อาร์กิวเมนต์:

  • tagName: สตริง
    • ชื่อแท็กเช่น "div" "span" เป็นต้น
  • withDataAndEvents: บูลีน
    • "บูลีนที่ระบุว่าควรคัดลอกตัวจัดการเหตุการณ์พร้อมกับองค์ประกอบหรือไม่ในขณะที่ jQuery 1.4 ข้อมูลองค์ประกอบจะถูกคัดลอกด้วย" ข้อมูล
  • deepWithDataAndEvents: บูลีน ,
    • บูลีนที่ระบุว่าควรคัดลอกตัวจัดการเหตุการณ์และข้อมูลสำหรับชายด์ทั้งหมดขององค์ประกอบที่โคลนหรือไม่ โดยค่าเริ่มต้นค่าจะตรงกับค่าของอาร์กิวเมนต์แรก (ซึ่งค่าเริ่มต้นเป็นเท็จ) " ข้อมูล

ผลตอบแทน:

องค์ประกอบ jQuery ที่สร้างขึ้นใหม่

โอเคฉันรู้ว่ามีคำตอบอยู่สองสามข้อที่นี่ แต่ฉันเอามันมาเขียนอีกครั้ง

ที่นี่เราสามารถแทนที่แท็กด้วยวิธีเดียวกับที่เราใช้การโคลน เรามีดังต่อไปนี้เช่นเดียวกับไวยากรณ์.clone ()ด้วยwithDataAndEventsและdeepWithDataAndEventsที่คัดลอกเด็กข้อมูลโหนดและเหตุการณ์ที่เกิดขึ้นหากมีการใช้

ตัวอย่าง:

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

ที่มา:

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

โปรดทราบว่าสิ่งนี้ไม่ได้แทนที่องค์ประกอบที่เลือก แต่จะส่งคืนองค์ประกอบที่สร้างขึ้นใหม่


2
โปรดทราบว่า.children()จะไม่มีโหนดข้อความใด ๆ ทั้งสิ้น คุณอาจต้องการลอง.contents()IIRC
Orwellophile

5

แนวคิดคือการรวมองค์ประกอบและแกะเนื้อหา:

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

ตัวอย่างการใช้งาน:

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

การสาธิต


0

ฉันคิดวิธีการที่คุณใช้การแสดงสตริงของวัตถุ jQuery ของคุณและแทนที่ชื่อแท็กโดยใช้นิพจน์ทั่วไปและ JavaScript พื้นฐาน คุณจะไม่สูญเสียเนื้อหาใด ๆ และไม่ต้องวนซ้ำแต่ละแอตทริบิวต์ / คุณสมบัติ

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

สุดท้ายคุณสามารถแทนที่วัตถุ / โหนดที่มีอยู่ได้ดังนี้:

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

0

นี่คือทางออกของฉัน อนุญาตให้สลับระหว่างแท็ก

<!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

นี่เป็นวิธีที่รวดเร็วในการเปลี่ยนแท็ก HTML ภายใน DOM ของคุณโดยใช้ jQuery ฉันพบว่าฟังก์ชันreplaceWith ()นี้มีประโยชน์มาก

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

0

คุณสามารถบรรลุโดยdata-*แอตทริบิวต์เช่นdata-replace="replaceTarget,replaceBy"นั้นด้วยความช่วยเหลือของ jQuery เพื่อรับreplaceTarget& replaceByมูลค่าตาม.split()วิธีหลังจากได้รับค่าแล้วใช้.replaceWith()วิธีการ เทคนิคแอตทริบิวต์
นี้data-*เพื่อจัดการการแทนที่แท็กได้อย่างง่ายดายโดยไม่ต้องเปลี่ยนแปลงด้านล่าง (โค้ดทั่วไปสำหรับการแทนที่แท็กทั้งหมด)

ฉันหวังว่าข้อมูลโค้ดด้านล่างจะช่วยคุณได้มาก

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

ฟังก์ชันต่อไปนี้ทำเคล็ดลับและเก็บแอตทริบิวต์ทั้งหมดไว้ คุณใช้ตัวอย่างเช่นนี้: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())
    })
  }
}

เพื่อให้แน่ใจว่าใช้งานได้ตรวจสอบตัวอย่างต่อไปนี้

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

มีเหตุผลเฉพาะที่คุณต้องเปลี่ยนแท็กหรือไม่? หากคุณแค่ต้องการทำให้ข้อความใหญ่ขึ้นการเปลี่ยนคลาส CSS ของแท็ก p จะเป็นวิธีที่ดีกว่าในการทำเช่นนั้น

สิ่งนี้:

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

เหตุผลที่ฉันขอให้เปลี่ยนองค์ประกอบ / แท็กเป็นเพราะฉันพยายามเปลี่ยนแท็ก (<h5> แม้ว่าประเภทจะไม่เกี่ยวข้อง) เป็น <input> เมื่อมีการคลิกปุ่ม "แก้ไข" ที่อื่นในหน้า .
Christopher Cooper
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.