Sử dụng jQuery để thay đổi thẻ HTML?


130

Điều này có thể không?

thí dụ:

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


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

Vì vậy, nhấp vào neo thay đổi sẽ khiến <p>Hello!</p>phần đó thay đổi thành (ví dụ) thẻ h5 để bạn kết thúc <h5>Hello!</h5>sau khi nhấp. Tôi nhận ra rằng bạn có thể xóa thẻ p và thay thế bằng h5, nhưng liệu có thực sự sửa đổi thẻ HTML không?

Câu trả lời:


211

Một khi một yếu tố dom được tạo ra, thẻ là bất biến, tôi tin. Bạn sẽ phải làm một cái gì đó như thế này:

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

2
Vui lòng xem nhận xét của tôi bên dưới ... thay đổi cấu trúc tài liệu để áp dụng kiểu không phải là cách tiếp cận tốt nhất.
jrista

39
Điều này sẽ không ghi đè bất kỳ thuộc tính nào có thể có trên thành phần bạn đã thay thế? Có thể dẫn đến một số hành vi không mong muốn do thuộc tính kiểu đã xóa, thuộc tính dữ liệu, v.v ...
Xavi

5
"<" + el.outerHTML.replace(/(^<\w+|\w+>$)/g, "H5") + ">";Hoặc hàm jQuery có thể cắm: link
húng

65

Đây là một tiện ích mở rộng sẽ làm tất cả, trên nhiều yếu tố theo nhiều cách ...

Ví dụ sử dụng:

giữ các lớp và thuộc tính hiện có:

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

hoặc là

Hủy lớp và thuộc tính hiện có:

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

hoặc thậm chí

thay thế tất cả các div bằng các nhịp, sao chép các lớp và thuộc tính, thêm tên lớp bổ sung

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

Nguồn 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
Vâng Và đối với hồ sơ, thực sự có rất nhiều lý do rất hợp lệ mà bạn có thể muốn thay đổi thẻ. ví dụ: nếu bạn có thẻ DIV trong SPAN, không chuẩn. Tôi đã sử dụng rất nhiều chức năng này trong khi làm việc với các tiêu chuẩn nghiêm ngặt của princexml để xuất bản pdb.
Orwellophile

1
Trông rất đẹp, mặc dù không may, nó mất tất cả các sự kiện của yếu tố thay thế. Có lẽ điều đó cũng có thể được xử lý - sẽ là tuyệt vời!
NPC

@NPC đó là cuộc sống ở thành phố lớn. nếu bạn định thay thế các yếu tố, sẽ có thương vong. Tôi chắc chắn có ai đó ngoài kia biết những
trò đùa

1
@FrankvanLuijn @orwellophile return node;thực sự nên được return this;hiển thị trong "phiên bản cũ" của plugin. Đây là bản chất cho các chuỗi sự kiện cùng nhau như$("tr:first").find("td").clone().replaceTag("li").appendTo("ul#list")
Cole Lawrence

1
Tôi không hiểu, tại sao bạn cần 2 chức năng? Bạn có cần cả hai? Xin lỗi, tôi bị lạc
João Pimentel Ferreira

12

Thay vì thay đổi loại thẻ, bạn nên thay đổi kiểu thẻ (hay đúng hơn là thẻ có id cụ thể.) Không nên thay đổi các yếu tố trong tài liệu của bạn để áp dụng các thay đổi về phong cách. Thử cái này:

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

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

3
Ngay cả trong trường hợp này, bạn không nên sửa đổi cấu trúc tài liệu của mình. Nếu bạn cần hiển thị đầu vào để phản hồi lại việc chỉnh sửa đang được nhấp, sau đó đặt đầu vào vào và hiển thị thanh: không có hoặc hiển thị: ẩn trên đó. Ẩn <h5> và hiển thị <input> để phản hồi với nút bấm. Nếu bạn liên tục sửa đổi cấu trúc tài liệu của mình ... bạn chỉ cần yêu cầu một loạt các vấn đề về kiểu dáng và bố cục.
jrista

1
Chắc chắn rồi. Javascript của bạn được nhúng hoặc liên kết, vì vậy nếu mối quan tâm của bạn là bảo mật, thì cách tiếp cận bảo mật của bạn có phần thiếu sót. Bạn nên kết xuất nội dung tài liệu của mình theo vai trò của người dùng ... trộn nội dung cho các vai trò không phải là cách an toàn để tiếp cận vấn đề. Nếu ai đó đăng nhập vào hệ thống của bạn với tư cách quản trị viên, hãy hiển thị nội dung cho quản trị viên. Nếu họ đăng nhập vào hệ thống của bạn dưới dạng trình đọc, hãy hiển thị nội dung cho trình đọc. Điều này loại bỏ hoàn toàn nội dung không nên truy cập. Khi nội dung được hiển thị, hãy sử dụng CSS để tạo kiểu cho tài liệu của bạn và hiển thị / ẩn nội dung.
jrista

2
Tôi đồng ý với bạn và đã đưa các khuyến nghị của bạn vào dự án. Tôi sẽ sử dụng toggle () để hiển thị các thành phần quản trị viên chỉ được hiển thị khi quản trị viên đăng nhập. Mặc dù không liên quan (trực tiếp) với câu hỏi ban đầu, đây có lẽ là một giải pháp tốt hơn so với hướng tôi đang đi ban đầu. Chúc mừng!
Christopher Cooper

1
Woo! Bỏ túi một blop của an ninh xấu! Một chiến thắng, và vòng cho tất cả! (chèn biểu tượng bia ở đây)
jrista

1
Dựa vào javascript phía máy khách để bảo mật thực sự là WORSE hơn là không có bảo mật nào cả. Tại sao? Bởi vì bạn nghĩ rằng bạn có bảo mật, trong khi thực tế bạn không có.
BryanH

8

Tôi nhận thấy rằng câu trả lời đầu tiên không hoàn toàn là những gì tôi cần, vì vậy tôi đã thực hiện một vài sửa đổi và hình dung tôi sẽ đăng nó trở lại đây.

Cải thiện replaceTag(<tagName>)

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

Tranh luận:

  • tagName: Chuỗi
    • Tên thẻ ví dụ: "div", "span", v.v.
  • withDataAndEvents: Boolean
    • "Boolean cho biết liệu trình xử lý sự kiện có nên được sao chép cùng với các phần tử hay không. Kể từ jQuery 1.4, dữ liệu phần tử cũng sẽ được sao chép." thông tin
  • deepWithDataAndEvents: Boolean ,
    • Boolean cho biết liệu trình xử lý sự kiện và dữ liệu cho tất cả con của phần tử nhân bản có nên được sao chép hay không. Theo mặc định, giá trị của nó khớp với giá trị của đối số đầu tiên (mặc định là sai). " Thông tin

Trả về:

Một phần tử jQuery mới được tạo

Được rồi, tôi biết có một vài câu trả lời ở đây bây giờ, nhưng tôi đã tự mình viết nó để viết lại.

Ở đây chúng ta có thể thay thế thẻ giống như cách chúng ta sử dụng nhân bản. Chúng tôi đang theo cùng một cú pháp như .clone () với withDataAndEventsdeepWithDataAndEventssao chép dữ liệu và sự kiện của các nút con nếu được sử dụng.

Thí dụ:

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

Nguồn:

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

Lưu ý rằng điều này không thay thế phần tử đã chọn, nó trả về phần tử mới được tạo.


2
Hãy lưu ý rằng .children()sẽ không bao gồm bất kỳ nút văn bản thuần túy. Bạn có thể muốn thử .contents()IIRC.
Orwellophile

5

Ý tưởng là bọc phần tử & mở khóa nội dung:

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

Sử dụng mẫu:

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

Bản giới thiệu


0

Tôi đã đưa ra một cách tiếp cận trong đó bạn sử dụng biểu diễn chuỗi của đối tượng jQuery của bạn và thay thế tên thẻ bằng các biểu thức thông thường và JavaScript cơ bản. Bạn sẽ không mất bất kỳ nội dung nào và không phải lặp lại từng thuộc tính / thuộc tính.

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

Cuối cùng, bạn có thể thay thế đối tượng / nút hiện có như sau:

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

0

Đây là giải pháp của tôi. Nó cho phép chuyển đổi giữa các thẻ.

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

Đây là cách nhanh chóng để thay đổi các thẻ HTML bên trong DOM của bạn bằng jQuery. Tôi thấy hàm thay thếWith () này rất hữu ích.

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

0

Bạn có thể đạt được bằng data-*thuộc tính như data-replace="replaceTarget,replaceBy"vậy với sự trợ giúp của jQuery để lấy replaceTarget& replaceByvalue theo .split()phương thức sau khi nhận giá trị rồi sử dụng .replaceWith()phương thức.
Đây data-*kỹ thuật thuộc tính để dễ dàng quản lý bất kỳ thay thế thẻ mà không thay đổi dưới đây (mã chung cho tất cả các thay tag).

Tôi hy vọng đoạn trích dưới đây sẽ giúp bạn rất nhiều.

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

Hàm sau thực hiện thủ thuật và giữ tất cả các thuộc tính. Bạn sử dụng nó ví dụ như thế này: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())
    })
  }
}

Để chắc chắn rằng nó hoạt động, kiểm tra ví dụ sau

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ó một lý do cụ thể mà bạn cần thay đổi thẻ? Nếu bạn chỉ muốn làm cho văn bản lớn hơn, thay đổi lớp CSS của thẻ p sẽ là cách tốt hơn để làm điều đó.

Một cái gì đó như thế này:

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

Lý do tôi yêu cầu thay đổi thành phần / thẻ là vì tôi đang cố gắng thay đổi thẻ (<h5>, mặc dù loại này không liên quan) thành <input> khi nhấp vào nút "chỉnh sửa" ở nơi khác trên trang .
Christopher Cooper
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.