J'ai le code suivant
<b class="xyzxterms" style="cursor: default; ">bryant keil bio</b>
Comment remplacer la b
balise par une h1
balise tout en conservant tous les autres attributs et informations?
J'ai le code suivant
<b class="xyzxterms" style="cursor: default; ">bryant keil bio</b>
Comment remplacer la b
balise par une h1
balise tout en conservant tous les autres attributs et informations?
Réponses:
Voici une façon de le faire avec jQuery:
var attrs = { };
$.each($("b")[0].attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
$("b").replaceWith(function () {
return $("<h1 />", attrs).append($(this).contents());
});
Exemple: http://jsfiddle.net/yapHk/
Mise à jour , voici un plugin:
(function($) {
$.fn.changeElementType = function(newType) {
var attrs = {};
$.each(this[0].attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
this.replaceWith(function() {
return $("<" + newType + "/>", attrs).append($(this).contents());
});
};
})(jQuery);
Exemple: http://jsfiddle.net/mmNNJ/
children
n'a pas marché mais ça l'a contents
fait.
.each
bloc comme le montre une réponse ci-dessous.
Pas sûr de jQuery. Avec JavaScript brut, vous pouvez faire:
var new_element = document.createElement('h1'),
old_attributes = element.attributes,
new_attributes = new_element.attributes;
// copy attributes
for(var i = 0, len = old_attributes.length; i < len; i++) {
new_attributes.setNamedItem(old_attributes.item(i).cloneNode());
}
// copy child nodes
do {
new_element.appendChild(element.firstChild);
}
while(element.firstChild);
// replace element
element.parentNode.replaceChild(new_element, element);
Je ne sais pas à quel point cela est compatible avec tous les navigateurs.
Une variation pourrait être:
for(var i = 0, len = old_attributes.length; i < len; i++) {
new_element.setAttribute(old_attributes[i].name, old_attributes[i].value);
}
Pour plus d'informations, voir Node.attributes
[MDN] .
while(child = child.nextSibling)
échoué. Merci!
@jakov et @Andrew Whitaker
Voici une amélioration supplémentaire pour qu'il puisse gérer plusieurs éléments à la fois.
$.fn.changeElementType = function(newType) {
var newElements = [];
$(this).each(function() {
var attrs = {};
$.each(this.attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
var newElement = $("<" + newType + "/>", attrs).append($(this).contents());
$(this).replaceWith(newElement);
newElements.push(newElement);
});
return $(newElements);
};
La réponse de @ Jazzbo a renvoyé un objet jQuery contenant un tableau d'objets jQuery, qui n'étaient pas chaînables. Je l'ai changé pour qu'il renvoie un objet plus similaire à ce que $ .each aurait renvoyé:
$.fn.changeElementType = function (newType) {
var newElements,
attrs,
newElement;
this.each(function () {
attrs = {};
$.each(this.attributes, function () {
attrs[this.nodeName] = this.nodeValue;
});
newElement = $("<" + newType + "/>", attrs).append($(this).contents());
$(this).replaceWith(newElement);
if (!newElements) {
newElements = newElement;
} else {
$.merge(newElements, newElement);
}
});
return $(newElements);
};
(J'ai également nettoyé le code pour qu'il passe jslint.)
each
boucle).
La seule façon dont je peux penser est de tout copier manuellement: exemple jsfiddle
HTML
<b class="xyzxterms" style="cursor: default; ">bryant keil bio</b>
Jquery / Javascript
$(document).ready(function() {
var me = $("b");
var newMe = $("<h1>");
for(var i=0; i<me[0].attributes.length; i++) {
var myAttr = me[0].attributes[i].nodeName;
var myAttrVal = me[0].attributes[i].nodeValue;
newMe.attr(myAttr, myAttrVal);
}
newMe.html(me.html());
me.replaceWith(newMe);
});
@Andrew Whitaker: Je propose ce changement:
$.fn.changeElementType = function(newType) {
var attrs = {};
$.each(this[0].attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
var newelement = $("<" + newType + "/>", attrs).append($(this).contents());
this.replaceWith(newelement);
return newelement;
};
Ensuite, vous pouvez faire des choses comme: $('<div>blah</div>').changeElementType('pre').addClass('myclass');
J'aime l'idée de @AndrewWhitaker et d'autres, d'utiliser un plugin jQuery - pour ajouter le changeElementType()
méthode. Mais un plugin est comme une boîte noire, peu importe le code, s'il est petit et fonctionne bien ... Donc, les performances sont requises, et sont plus importantes que le code.
"Pure javascript" a de meilleures performances que jQuery: je pense que le code de @ FelixKling a de meilleures performances que celui de @ AndrewWhitaker et d'autres.
Voici un code "pur Javavascript" (et "pur DOM"), encapsulé dans un plugin jQuery :
(function($) { // @FelixKling's code
$.fn.changeElementType = function(newType) {
for (var k=0;k<this.length; k++) {
var e = this[k];
var new_element = document.createElement(newType),
old_attributes = e.attributes,
new_attributes = new_element.attributes,
child = e.firstChild;
for(var i = 0, len = old_attributes.length; i < len; i++) {
new_attributes.setNamedItem(old_attributes.item(i).cloneNode());
}
do {
new_element.appendChild(e.firstChild);
}
while(e.firstChild);
e.parentNode.replaceChild(new_element, e);
}
return this; // for chain... $(this)? not working with multiple
}
})(jQuery);
Voici une méthode que j'utilise pour remplacer les balises html dans jquery:
// Iterate over each element and replace the tag while maintaining attributes
$('b.xyzxterms').each(function() {
// Create a new element and assign it attributes from the current element
var NewElement = $("<h1 />");
$.each(this.attributes, function(i, attrib){
$(NewElement).attr(attrib.name, attrib.value);
});
// Replace the current element with the new one and carry over the contents
$(this).replaceWith(function () {
return $(NewElement).append($(this).contents());
});
});
jQuery
sans itération sur les attributs:La replaceElem
méthode accepte ci - dessous old Tag
, new Tag
et context
et exécute avec succès le remplacement:
replaceElem('h2', 'h1', '#test');
function replaceElem(oldElem, newElem, ctx) {
oldElems = $(oldElem, ctx);
//
$.each(oldElems, function(idx, el) {
var outerHTML, newOuterHTML, regexOpeningTag, regexClosingTag, tagName;
// create RegExp dynamically for opening and closing tags
tagName = $(el).get(0).tagName;
regexOpeningTag = new RegExp('^<' + tagName, 'i');
regexClosingTag = new RegExp(tagName + '>$', 'i');
// fetch the outer elem with vanilla JS,
outerHTML = el.outerHTML;
// start replacing opening tag
newOuterHTML = outerHTML.replace(regexOpeningTag, '<' + newElem);
// continue replacing closing tag
newOuterHTML = newOuterHTML.replace(regexClosingTag, newElem + '>');
// replace the old elem with the new elem-string
$(el).replaceWith(newOuterHTML);
});
}
h1 {
color: white;
background-color: blue;
position: relative;
}
h1:before {
content: 'this is h1';
position: absolute;
top: 0;
left: 50%;
font-size: 5px;
background-color: black;
color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">
<h2>Foo</h2>
<h2>Bar</h2>
</div>
Bonne chance...
Solution Javascript
Copiez les attributs de l'ancien élément dans le nouvel élément
const $oldElem = document.querySelector('.old')
const $newElem = document.createElement('div')
Array.from($oldElem.attributes).map(a => {
$newElem.setAttribute(a.name, a.value)
})
Remplacez l'ancien élément par le nouvel élément
$oldElem.parentNode.replaceChild($newElem, $oldElem)
map
crée un nouveau tableau inutilisé, il pourrait être remplacé par forEach
.
Voici ma version. Il s'agit essentiellement de la version de @ fiskhandlarn, mais au lieu de construire un nouvel objet jQuery, il écrase simplement les anciens éléments par ceux nouvellement créés, donc aucune fusion n'est nécessaire.
Démo: http://jsfiddle.net/0qa7wL1b/
$.fn.changeElementType = function( newType ){
var $this = this;
this.each( function( index ){
var atts = {};
$.each( this.attributes, function(){
atts[ this.name ] = this.value;
});
var $old = $(this);
var $new = $('<'+ newType +'/>', atts ).append( $old.contents() );
$old.replaceWith( $new );
$this[ index ] = $new[0];
});
return this;
};