使用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标签?

Answers:


211

我相信,一旦创建了dom元素,该标签就不会更改。您必须执行以下操作:

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

2
请在下面查看我的评论...更改文档结构以应用样式不是最佳方法。
jrista

39
这个替换对象不会在替换的元素上包含任何属性吗?由于删除了样式属性,数据属性等,可能导致某些意外行为……
Xavi

5
"<" + el.outerHTML.replace(/(^<\w+|\w+>$)/g, "H5") + ">";或可插入的jQuery函数:链接
罗勒2015年

65

这是一个扩展,它将以多种方式在所有元素上完成所有工作...

用法示例:

保留现有的类和属性:

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

要么

丢弃现有的类和属性:

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

甚至

用span替换所有div,复制类和属性,添加额外的类名

$('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
对。为了记录在案,实际上有很多非常有效的原因,您可能想更改标签。例如,如果您在SPAN中有DIV标签,这是非标准的。在使用princexml的严格标准进行pdb发布时,我从该功能中获得了很多使用。
Orwellophile

1
看起来非常不错,尽管很遗憾,它丢失了替换元素的所有事件。也许也可以解决-太棒了!
NPC

@NPC就是大城市的生活。如果您要替换元素,将会有人员伤亡。我确定那里有人知道相关的jquery来克隆事件:)
Orwellophile 2013年

1
@FrankvanLuijn @orwellophile return node;实际上应该return this;如插件的“旧版本”中所示。这对于将事件链接在一起至关重要,例如$("tr:first").find("td").clone().replaceTag("li").appendTo("ul#list")
Cole Lawrence

1
我不明白,为什么需要2个功能?你们都需要吗?对不起,我迷路了
若昂·皮门特尔费雷拉

12

而不是更改标签的类型,您应该更改标签的样式(或者更确切地说,是具有特定ID的标签)。更改文档元素以应用样式更改不是一个好习惯。试试这个:

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

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

3
即使在这种情况下,您也不应修改文档结构。如果您需要显示输入来响应单击编辑对接的情况,则将输入放进去,并在其上保留display:none或visible:隐藏。隐藏<h5>并显示<input>以响应单击按钮。如果您要不断修改文档结构...您只是在问路途中一大堆样式和布局问题。
jrista

1
绝对。您的JavaScript是嵌入式的或链接的,因此,如果您关注安全性,那么您的安全性方法就会有些瑕疵。您应该根据用户的角色来呈现文档的内容...为角色混合内容不是解决问题的安全方法。如果有人以管理员身份登录到您的系统,请呈现管理员的内容。如果它们以读取器的身份登录到您的系统,请为读取器呈现内容。这完全消除了不应访问的内容。呈现内容后,使用CSS设置文档样式并显示/隐藏内容。
jrista

2
我同意您的意见,并已将您的建议纳入项目。我将使用toggle()来显示仅在管理员登录时才呈现的admin元素。尽管与原始问题无关(直接相关),但这可能是比我最初的方向更好的解决方案。干杯!
Christopher Cooper,2009年

1
!袋装另一个安全不良的斑点!一场胜利,为所有人而战!(在此处插入啤酒图标)
克里斯塔2009年

1
依靠客户端javascript来实现安全性实际上是WORSE,而不是根本没有安全性。为什么?因为您认为自己具有安全性,但实际上却没有。
BryanH 2011年

8

我注意到第一个答案并不完全符合我的需要,因此我作了一些修改,以为可以将其发布回这里。

已改善 replaceTag(<tagName>)

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

参数:

  • tagName:字符串
    • 标签名称,例如“ div”,“ span”等。
  • withDataAndEvents:布尔值
    • “一个布尔值,指示是否应将事件处理程序与元素一起复制。从jQuery 1.4开始,还将复制元素数据。” 信息
  • deepWithDataAndEvents:布尔值
    • 一个布尔值,指示是否应复制克隆元素的所有子级的事件处理程序和数据。默认情况下,其值与第一个参数的值匹配(默认为false)。” info

返回值:

新创建的jQuery元素

好的,我知道现在有一些答案,但是我自己想再写一次。

在这里,我们可以像使用克隆一样替换标签。我们使用与.clone()相同的语法,并使用withDataAndEventsdeepWithDataAndEvents,如果使用了节点,则会复制节点的数据和事件。

例:

$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

这是使用jQuery更改DOM内部HTML标签的快速方法。我发现这个replaceWith()函数非常有用。

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

0

您可以在jQuery的帮助下通过data-*属性来实现,data-replace="replaceTarget,replaceBy"从而在获取值然后使用method时按方法获取replaceTargetreplaceBy值。 此属性技术可轻松管理任何标签替换而无需在下面进行更改(所有标签替换的通用代码)。 希望以下摘要对您有所帮助。.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

是否有特定原因需要更改标签?如果只想扩大文本范围,那么更改p标签的CSS类将是一个更好的方法。

像这样:

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

我要求更改元素/标签的原因是因为当我在页面的其他位置单击“编辑”按钮时,试图将标签(<h5>,尽管类型无关)更改为<input> 。
克里斯托弗·库珀
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.