web-dev-qa-db-fra.com

jQuery: comment changer le nom de la balise?

jQuery: comment changer le nom de la balise?

Par exemple:

<tr>
    $1
</tr>

J'ai besoin

<div>
    $1
</div>

Oui je peux

  1. Créer un élément DOM <div>
  2. Copier le contenu de tr
  3. Retirer tr de dom

Mais puis-je le faire directement?

PS:

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

résultats dans DOMException.

53
puchu

Vous pouvez remplacer n'importe quel balisage HTML en utilisant la méthode .replaceWith() de jQuery.

exemple: http://jsfiddle.net/JHmaV/

Réf .: . replaceWith

Si vous souhaitez conserver le balisage existant, vous pouvez utiliser le code suivant:

$('#target').replaceWith('<newTag>' + $('target').html() +'</newTag>')
35
jAndy

Non, ce n'est pas possible selon les spécifications du W3C: "tagName de type DOMString, en lecture seule"

http://www.w3.org/TR/DOM-Level-2-Core/core.html

43
ggarber

Où la méthode DOM renameNode ()?

Aujourd'hui (2014), aucun navigateur ne comprend la nouvelle méthode DOM3 renameNode (voir également le W3C ), vérifiez si elle est exécutée sur votre bowser: http://jsfiddle.net/ k2jSm/1 /

Donc, une solution DOM est moche et je ne comprends pas pourquoi (??) jQuery n’a pas implémenté de solution de contournement?

algorithme DOM pur

  1. createElement(new_name)
  2. copier tout le contenu dans le nouvel élément;
  3. remplacez l'ancien par le nouveau par replaceChild()

est quelque chose comme ça,

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

... attendez avis et jsfiddle ...

algorithme jQuery

L’algorithme @ilpoldo est un bon point de départ,

   $from.replaceWith($('<'+newname+'/>').html($from.html()));

Comme d'autres l'ont commenté, il faut une copie d'attribut ... attendez générique ...

spécifique pour class, en préservant l'attribut , voir http://jsfiddle.net/cDgpS/

Voir aussi https://stackoverflow.com/a/9468280/287948

13
Peter Krauss

Les solutions ci-dessus suppriment l'élément existant et le recréent à partir de zéro, en détruisant les liaisons d'événements sur les enfants dans le processus.

réponse courte: (perd les attributs)

$("p").wrapInner("<div/>").children(0).unwrap();

réponse plus longue: (attributs de la copie)

$("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 avec des liaisons imbriquées

Il serait bien de copier toutes les liaisons en même temps, mais obtenir les liaisons actuelles ne fonctionnait pas pour moi.

9
ericP

Pour conserver le contenu interne de la balise, vous pouvez utiliser l'accesseur .html() conjointement avec .replaceWith().

exemple forké: http://jsfiddle.net/WVb2Q/1/

7
ilpoldo

Vous pourriez aller un peu de base. Travaille pour moi.

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;
2
Cory

Inspiré par ericP answer, formaté et converti en plugin jQuery:

$.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')
1
Dmitriy Sintsov

JS pour changer le nom de la balise

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

Le violon associé est dans ce link

1
illusionist

Pour remplacer le contenu interne des balises multiple, chacune avec son propre contenu d'origine, vous devez utiliser .replaceWith() et .html() différemment:

http://jsfiddle.net/kcrca/VYxxG/

1
user856027

Puisque replaceWith() ne fonctionnait pas pour moi sur un élément (peut-être parce que je l’avais utilisé dans map()), je l’ai fait en créant un nouvel élément et en copiant les attributs au besoin.

$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);
0
WoodrowShigeru

Encore un autre script pour changer le nom du noeud

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/

Il copiera les attributs et le code HTML interne dans un nouvel élément, puis remplacera l'ancien.

0
Berty

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

0
Ifeanyi Chukwu

Prends-le par la Parole

Prise de la question par Word "comment changer le nom de la balise?" Je suggérerais cette solution:
Si cela a du sens ou non, cela doit être décidé au cas par cas.

Mon exemple va "renommer" tous les balises a avec des hyperliens pour SMS avec des balises span. Maintenir tous les attributs et le contenu:

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

Comme cela n’a aucun sens d’avoir une balise span avec un attribut href, je le supprime aussi . Le faire de cette façon est comme une solution pare-balles et compatible avec tous les navigateurs pris en charge par jquery . copier tous les attributs dans le nouvel élément, mais ceux-ci ne sont pas compatibles avec tous les navigateurs.

Bien que je pense que cela coûte assez cher de le faire de cette façon.

0

Jquery plugin pour rendre "tagName" éditable:

(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);

Voir: http://jsfiddle.net/03gcnx9v/3/

0
cedrik

Vous pouvez utiliser cette fonction 

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

Exemple de code

renameTag($(tr),'div');
0
Sarath Ak

Changer simplement les valeurs des propriétés ne le fera pas (comme d'autres l'ont déjà dit, certaines propriétés HTMLElement sont en lecture seule; certaines détiennent également un contexte prototype pour des éléments plus primitifs). La chose la plus proche que vous puissiez avoir pour imiter l'API DOM est d'imiter également le processus d'héritage prototypique en JavaScript. 

'Paramétrer' sur le prototype d'un objet via __proto__ est généralement mal vu. En outre, vous pourriez peut-être comprendre pourquoi vous pensez avoir besoin de dupliquer tout l'élément DOM en premier lieu. Mais voici:

// Define this at whatever scope you'll need to access it
// Most of these kinds of constructors are attached to the `window` object

window.HTMLBookElement = function() {

  function HTMLBookElement() {
    var book = document.createElement('book');
    book.__proto__ = document.createElement('audio');
    return book;
  }

  return new HTMLBookElement();

}

// Test your new element in a console (I'm assuming you have Chrome)

var harryPotter = new HTMLBookElement();

// You should have access to your new `HTMLBookElement` API as well as that
// of its prototype chain; since I prototyped `HTMLAudioElement`, you have 
// some default properties like `volume` and `preload`:

console.log(harryPotter);         // should log "<book></book>"
console.log(harryPotter.volume);  // should log "1"
console.log(harryPotter.preload); // should log "auto"

Tous les éléments DOM fonctionnent de cette façon. Par exemple: <div></div> est produit par HTMLDivElement, Qui étend HTMLElement, Qui étend Element, Qui étend Object.

0
Benny