jQuery: how to change tag name?

76,370

Solution 1

You 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>')

Solution 2

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

Solution 3

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

  1. createElement(new_name)
  2. copy all content to new element;
  3. 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

Solution 4

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.

Solution 5

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/

Share:
76,370
puchu
Author by

puchu

Updated on July 05, 2022

Comments

  • puchu
    puchu almost 2 years

    jQuery: how to change tag name?

    For example:

    <tr>
        $1
    </tr>
    

    I need

    <div>
        $1
    </div>
    

    Yes, I can

    1. Create DOM element <div>
    2. Copy tr content to div
    3. Remove tr from dom

    But can I make it directly?

    PS:

        $(tr).get(0).tagName = "div"; 
    

    results in DOMException.

  • Jason
    Jason about 13 years
    This will work, but you won't carry over the dom element's properties (styles, events) etc. I don't think there exists a good way to really achieve a full node name change.
  • Admin
    Admin almost 13 years
    how about saving all attributes of any element?
  • I.G. Pascual
    I.G. Pascual almost 13 years
    just what i was searching for +1. Attributes are not included with other solutions, until now, this one is a better one
  • Grinn
    Grinn almost 12 years
    No, it doesn't preserve the attributes.
  • Peter Krauss
    Peter Krauss about 10 years
    Sorry, it is NOT a "rename", it destroy all contents (all innerHTML changes!).
  • Peter Krauss
    Peter Krauss about 10 years
    I thing que puchu's question is only about "rename procedure" (!), and there are a "DOM ugly way" to do rename: 1) createElement(new_name) 2) copy all content to new element; 3) replace old to new by replaceChild()
  • Peter Krauss
    Peter Krauss about 10 years
    Yes... But it is in the right direction! It is a "rename procedure"... Complement it with a attribute-copy, stackoverflow.com/a/6753486/287948, or using clone.
  • Peter Krauss
    Peter Krauss about 10 years
    It is a copy of @ilpoldo solution, and can be better as commented there. A copy-solution must be deleted.
  • Peter Krauss
    Peter Krauss about 10 years
    It is not jQuery and is replace string is not a secure or generic strategy, use DOM or jQuery.
  • pat capozzi
    pat capozzi over 9 years
    I used this as jquery mobile sometimes generates double selects
  • Benny Schmidt
    Benny Schmidt about 9 years
    @PeterKrauss I don't know why my answer is here haha (was it moved?) -- this is supposed to be the answer for "how to create a custom html element"
  • Peter Krauss
    Peter Krauss about 9 years
    hum... check the "finger" what occured... stackoverflow.com/posts/3435871/revisions Is (perhaps) a Stackoverflow dynamic problem...
  • Benny Schmidt
    Benny Schmidt about 9 years
    i do not understand what you say
  • Peter Krauss
    Peter Krauss about 9 years
    Sorry, I will delete: the term "finger" has conotation (in the 70's) of "is a snitch" (and UNIX preserved some decades as finger command popularity)... We can say that an history of revisions like this is a "finger" (or "snitch") of the user actions... Well, the "dynamic of the user actions (at Stackoverflow)": can be normal or can be problematic, because the user can change the question when somebody, like you, already answered the first version of the question.
  • Ari
    Ari almost 9 years
    it is a replace, not rename!
  • Admin
    Admin almost 8 years
    Well to keep events etc of the contents, one could have .replaceWith($('<newTag>').append($('#target').contents())
  • Nils Lindemann
    Nils Lindemann about 3 years
    Pretty modern code, and works. Usage example: $('blockquote').each(function(){let ren = rename_element(this, 'div'); $(ren).doMoreJqueryStuff()})
  • Nils Lindemann
    Nils Lindemann about 3 years
    <div data-divanslation="now you are in divouble">...</div>