jQuery: comment changer le nom de la balise?
Par exemple:
<tr>
$1
</tr>
J'ai besoin
<div>
$1
</div>
Oui je peux
Mais puis-je le faire directement?
PS:
$(tr).get(0).tagName = "div";
résultats dans DOMException
.
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>')
Non, ce n'est pas possible selon les spécifications du W3C: "tagName de type DOMString, en lecture seule"
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?
createElement(new_name)
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 ...
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
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.
Pour conserver le contenu interne de la balise, vous pouvez utiliser l'accesseur .html()
conjointement avec .replaceWith()
.
exemple forké: http://jsfiddle.net/WVb2Q/1/
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;
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')
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
Pour remplacer le contenu interne des balises multiple, chacune avec son propre contenu d'origine, vous devez utiliser .replaceWith()
et .html()
différemment:
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);
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.
$(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>
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.
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);
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');
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
.