admin管理员组文章数量:1134247
jQuery: how to change tag name?
For example:
<tr>
$1
</tr>
I need
<div>
$1
</div>
Yes, I can
- Create DOM element <div>
- Copy tr content to div
- Remove tr from dom
But can I make it directly?
PS:
$(tr).get(0).tagName = "div";
results in DOMException
.
jQuery: how to change tag name?
For example:
<tr>
$1
</tr>
I need
<div>
$1
</div>
Yes, I can
- Create DOM element <div>
- Copy tr content to div
- Remove tr from dom
But can I make it directly?
PS:
$(tr).get(0).tagName = "div";
results in DOMException
.
19 Answers
Reset to default 58You can replace any HTML markup by using jQuery's .replaceWith()
method.
example: http://jsfiddle.net/JHmaV/
Ref.: .replaceWith
If you want to keep the existing markup, you could use code like this:
$('#target').replaceWith('<newTag>' + $('#target').html() +'</newTag>')
No, it is not possible according to W3C specification: "tagName of type DOMString, readonly"
http://www.w3.org/TR/DOM-Level-2-Core/core.html
The above solutions wipe out the existing element and re-create it from scratch, destroying any event bindings on children in the process.
short answer: (loses <p/>'s attributes)
$("p").wrapInner("<div/>").children(0).unwrap();
longer answer: (copies <p/>'s attributes)
$("p").each(function (o, elt) {
var newElt = $("<div class='p'/>");
Array.prototype.slice.call(elt.attributes).forEach(function(a) {
newElt.attr(a.name, a.value);
});
$(elt).wrapInner(newElt).children(0).unwrap();
});
fiddle with nested bindings
It would be cool to copy any bindings from the at the same time, but getting current bindings didn't work for me.
Where the DOM renameNode() Method?
Today (2014) no browser understand the new DOM3 renameNode method (see also W3C) check if run at your bowser: http://jsfiddle.net/k2jSm/1/
So, a DOM solution is ugly and I not understand why (??) jQuery not implemented a workaround?
pure DOM algorithm
createElement(new_name)
- copy all content to new element;
- replace old to new by
replaceChild()
is something like this,
function rename_element(node,name) {
var renamed = document.createElement(name);
foreach (node.attributes as a) {
renamed.setAttribute(a.nodeName, a.nodeValue);
}
while (node.firstChild) {
renamed.appendChild(node.firstChild);
}
return node.parentNode.replaceChild(renamed, node);
}
... wait review and jsfiddle ...
jQuery algorithm
The @ilpoldo algorithm is a good start point,
$from.replaceWith($('<'+newname+'/>').html($from.html()));
As others commented, it need a attribute copy ... wait generic ...
specific for class
, preserving the attribute, see http://jsfiddle.net/cDgpS/
See also https://stackoverflow.com/a/9468280/287948
To preserve the internal content of the tag you can use the accessor .html()
in conjunction with .replaceWith()
forked example: http://jsfiddle.net/WVb2Q/1/
Inspired by ericP answer, formatted and converted to jQuery plugin:
$.fn.replaceWithTag = function(tagName) {
var result = [];
this.each(function() {
var newElem = $('<' + tagName + '>').get(0);
for (var i = 0; i < this.attributes.length; i++) {
newElem.setAttribute(
this.attributes[i].name, this.attributes[i].value
);
}
newElem = $(this).wrapInner(newElem).children(0).unwrap().get(0);
result.push(newElem);
});
return $(result);
};
Usage:
$('div').replaceWithTag('span')
Working pure DOM algorithm
function rename_element(node, name) {
let renamed = document.createElement(name);
Array.from(node.attributes).forEach(attr => {
renamed.setAttribute(attr.name, attr.value);
})
while (node.firstChild) {
renamed.appendChild(node.firstChild);
}
node.parentNode.replaceChild(renamed, node);
return renamed;
}
You could go a little basic. Works for me.
var oNode = document.getElementsByTagName('tr')[0];
var inHTML = oNode.innerHTML;
oNode.innerHTML = '';
var outHTML = oNode.outerHTML;
outHTML = outHTML.replace(/tr/g, 'div');
oNode.outerHTML = outHTML;
oNode.innerHTML = inHTML;
To replace the internal contents of multiple tags, each with their own original content, you have to use .replaceWith()
and .html()
differently:
http://jsfiddle.net/kcrca/VYxxG/
JS to change the tag name
/**
* This function replaces the DOM elements's tag name with you desire
* Example:
* replaceElem('header','ram');
* replaceElem('div.header-one','ram');
*/
function replaceElem(targetId, replaceWith){
$(targetId).each(function(){
var attributes = concatHashToString(this.attributes);
var replacingStartTag = '<' + replaceWith + attributes +'>';
var replacingEndTag = '</' + replaceWith + '>';
$(this).replaceWith(replacingStartTag + $(this).html() + replacingEndTag);
});
}
replaceElem('div','span');
/**
* This function concats the attributes of old elements
*/
function concatHashToString(hash){
var emptyStr = '';
$.each(hash, function(index){
emptyStr += ' ' + hash[index].name + '="' + hash[index].value + '"';
});
return emptyStr;
}
Related fiddle is in this link
You can use this function
var renameTag = function renameTag($obj, new_tag) {
var obj = $obj.get(0);
var tag = obj.tagName.toLowerCase();
var tag_start = new RegExp('^<' + tag);
var tag_end = new RegExp('<\\/' + tag + '>$');
var new_html = obj.outerHTML.replace(tag_start, "<" + new_tag).replace(tag_end, '</' + new_tag + '>');
$obj.replaceWith(new_html);
};
ES6
const renameTag = function ($obj, new_tag) {
let obj = $obj.get(0);
let tag = obj.tagName.toLowerCase();
let tag_start = new RegExp('^<' + tag);
let tag_end = new RegExp('<\\/' + tag + '>$');
let new_html = obj.outerHTML.replace(tag_start, "<" + new_tag).replace(tag_end, '</' + new_tag + '>');
$obj.replaceWith(new_html);
};
Sample code
renameTag($(tr),'div');
Since replaceWith()
didn't work for me on an element basis (maybe because I used it inside map()
), I did it by creating a new element and copying the attributes as needed.
$items = $('select option').map(function(){
var
$source = $(this),
$copy = $('<li></li>'),
title = $source.text().replace( /this/, 'that' );
$copy
.data( 'additional_info' , $source.val() )
.text(title);
return $copy;
});
$('ul').append($items);
Take him by the word
Taken the Question by Word "how to change tag name?" I would suggest this solution:
If it makes sense or not has to be decided case by case.
My example will "rename" all a-Tags with hyperlinks for SMS with span tags. Maintaining all attributes and content:
$('a[href^="sms:"]').each(function(){
var $t=$(this);
var $new=$($t.wrap('<div>')
.parent()
.html()
.replace(/^\s*<\s*a/g,'<span')
.replace(/a\s*>\s*$/g,'span>')
).attr('href', null);
$t.unwrap().replaceWith($new);
});
As it does not make any sense to have a span tag with an href attribute I remove that too. Doing it this way is bulletproof and compatible with all browsers that are supported by jquery. There are other ways people try to copy all the Attributes to the new Element, but those are not compatible with all browsers.
Although I think it is quite expensive to do it this way.
Jquery plugin to make "tagName" editable :
(function($){
var $newTag = null;
$.fn.tagName = function(newTag){
this.each(function(i, el){
var $el = $(el);
$newTag = $("<" + newTag + ">");
// attributes
$.each(el.attributes, function(i, attribute){
$newTag.attr(attribute.nodeName, attribute.nodeValue);
});
// content
$newTag.html($el.html());
$el.replaceWith($newTag);
});
return $newTag;
};
})(jQuery);
See : http://jsfiddle.net/03gcnx9v/3/
Yet another script to change the node name
function switchElement() {
$element.each(function (index, oldElement) {
let $newElement = $('<' + nodeName + '/>');
_.each($element[0].attributes, function(attribute) {
$newElement.attr(attribute.name, attribute.value);
});
$element.wrapInner($newElement).children().first().unwrap();
});
}
http://jsfiddle.net/rc296owo/5/
It will copy over the attributes and inner html into a new element and then replace the old one.
$(function(){
$('#switch').bind('click', function(){
$('p').each(function(){
$(this).replaceWith($('<div/>').html($(this).html()));
});
});
});
p {
background-color: red;
}
div {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Hello</p>
<p>Hello2</p>
<p>Hello3</p>
<button id="switch">replace</button>
Try this one also. in this example we can also have attributes of the old tag in new tag
var newName = document.querySelector('.test').outerHTML.replaceAll('h1', 'h2');
document.querySelector('.test').outerHTML = newName;
<h1 class="test">Replace H1 to H2</h1>
Assume you enabled jQuery
- Get the Html-code of DOM.
- Replace the TAG in Html-code
- Convert Html-code to DOM
here comes the sample code, it is ugly, but work, lol.
DOM_old = $('<td>contents</td>');
temp = DOM_old[0].outerHTML;
temp = temp.replace('<td', '<div');
temp = temp.replace('</td>', '</div>');
DOM_new = $(temp);
As the accepted answer have some limitations (like the attributes aren't migrated to the new element), I found a new way to replace tag name without loosing those. But it also have some limitations for example: The events set to the main element will not migrated to the new element. Anyways, I'm providing the function. Let me know if you have any better Idea.
With Pure Javascript:
function replaceTag(element, new_tag) {
let outerHTML = element.outerHTML;
let outerTag = outerHTML
.match(/<([a-zA-Z]*?)( |>)/)[0]
.replaceAll("<", "")
.replaceAll("/", "")
.replaceAll("=", "")
.replaceAll(">", "")
.trim();
let newHTML_pre = outerHTML.replace(outerTag, new_tag);
newHTML_pre = newHTML_pre.slice(0, newHTML_pre.length - outerTag.length - 3);
let newHTML;
if (outerHTML.endsWith('</' + outerTag + '>')) {
newHTML = newHTML_pre + '</' + new_tag + '>';
} else {
newHTML = newHTML_pre;
}
element.outerHTML = newHTML;
}
// let e = document.querySelector('div');
// replaceTag(e, 'img');
With Jquery:
$.fn.replaceTag = function (new_tag) {
return this.each(function () {
let outerHTML = $(this).prop("outerHTML");
let outerTag = outerHTML
.match(/<([a-zA-Z]*?)( |>)/)[0]
.replaceAll("<", "")
.replaceAll("/", "")
.replaceAll("=", "")
.replaceAll(">", "")
.trim();
let newHTML_pre = outerHTML.replace(outerTag, new_tag);
newHTML_pre = newHTML_pre.slice(0, newHTML_pre.length - outerTag.length - 3);
let newHTML;
if (outerHTML.endsWith("</" + outerTag + ">")) {
newHTML = newHTML_pre + "</" + new_tag + ">";
} else {
newHTML = newHTML_pre;
}
$(this).prop("outerHTML", newHTML);
});
};
// $('div').replaceTag('img');
Explanation:
The function replaces the start and end tag of the element's outerHTML with the new tag ignoring the child elements with the same tag name. Sometimes the element doesn't have end tag name like: (<div />
), in that case it just replace the start tag. That's All.
本文标签: javascriptjQuery how to change tag nameStack Overflow
版权声明:本文标题:javascript - jQuery: how to change tag name? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736807041a1953733.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
div
won't be a valid element wheretr
is located. – Felix Kling Commented Aug 8, 2010 at 20:11display:block
to make atr
act and look like adiv
without actually changing the tag name but you would probably want todisplay:block
ify the innertd
s as well with something liketr,tr>td{display:block}
. – oriadam Commented Jan 24, 2021 at 9:09