web-dev-qa-db-fra.com

Obtenir le code HTML externe de l'élément sélectionné

J'essaie d'obtenir le code HTML d'un objet sélectionné avec jQuery. Je connais la fonction .html(); le problème est que j'ai besoin du HTML, y compris de l'objet sélectionné (une ligne de tableau dans ce cas, où .html() ne renvoie que les cellules à l'intérieur de la ligne).

J’ai cherché et trouvé quelques méthodes très "hackish" pour cloner un objet, l’ajouter à un div nouvellement créé, etc., etc., mais cela semble vraiment sale. Existe-t-il un meilleur moyen ou la nouvelle version de jQuery (1.4.2) offre-t-elle une fonctionnalité de type outerHtml?

757
Ryan

2014 Edit: La question et cette réponse datent de 2010. À l'époque, aucune meilleure solution n'était largement disponible. Maintenant, beaucoup d'autres réponses sont meilleures: Eric Hu, ou Re Capcha, par exemple.

Ce site semble avoir une solution pour vous: jQuery: outerHTML | Yelotofu

jQuery.fn.outerHTML = function(s) {
    return s
        ? this.before(s).remove()
        : jQuery("<p>").append(this.eq(0).clone()).html();
};
182
David V.

Je crois qu'actuellement (5/1/2012), tous les principaux navigateurs supportent la fonction outerHTML. Il me semble que cet extrait est suffisant. Personnellement, je choisirais de mémoriser ceci:

// Gives you the DOM element without the outside wrapper you want
$('.classSelector').html()

// Gives you the outside wrapper as well only for the first element
$('.classSelector')[0].outerHTML

// Gives you the outer HTML for all the selected elements
var html = '';
$('.classSelector').each(function () {
    html += this.outerHTML;
});

//Or if you need a one liner for the previous code
$('.classSelector').get().map(function(v){return v.outerHTML}).join();

EDIT: Statistiques de support de base pour element.outerHTML

642
Eric Hu

Pas besoin de générer une fonction pour cela. Fais-le comme ça:

$('a').each(function(){
    var s = $(this).clone().wrap('<p>').parent().html();
    console.log(s);
});

(La console de votre navigateur indiquera ce qui est journalisé, soit dit en passant. La plupart des navigateurs les plus récents depuis 2009 ont cette fonctionnalité.)

La magie est la suivante:

.clone().wrap('<p>').parent().html();

Le clone signifie que vous ne dérangez pas réellement le DOM. Exécutez-le sans cela et vous verrez les balises p insérées avant/après tous les hyperliens (dans cet exemple), ce qui n'est pas souhaitable. Donc, oui, utilisez .clone().

Cela fonctionne de la manière suivante: il prend chaque balise a, en crée un clone dans la RAM, le recouvre de balises p, en obtient le parent (signifiant la balise p), puis la propriété innerHTML.

EDIT: pris conseil et changé les balises div en p parce que c’est moins typé et qui fonctionne de la même manière.

341
Volomike

Qu'en est-il de: prop('outerHTML')?

var outerHTML_text = $('#item-to-be-selected').prop('outerHTML');

Et pour régler:

$('#item-to-be-selected').prop('outerHTML', outerHTML_text);

Cela a fonctionné pour moi.

PS: Ceci est ajouté dans jQuery 1.6 .

136
Re Captcha

Étendre jQuery:

(function($) {
  $.fn.outerHTML = function() {
    return $(this).clone().wrap('<div></div>').parent().html();
  };
})(jQuery);

Et utilisez-le comme ceci: $("#myTableRow").outerHTML();

89
jessica

Je suis d'accord avec Arpan (déc 13 '10 5:59).

Sa façon de le faire est en fait une bien meilleure façon de le faire, car vous n’utilisez pas de clone. La méthode de clonage prend beaucoup de temps, si vous avez des éléments enfants et que personne d'autre ne semble s'inquiéter du fait que IE a réellement l'attribut outerHTML (oui, oui IE a QUELQUES astuces utiles).

Mais je créerais probablement son script un peu différent:

$.fn.outerHTML = function() {
    var $t = $(this);
    if ($t[0].outerHTML !== undefined) {
        return $t[0].outerHTML;
    } else {
        var content = $t.wrap('<div/>').parent().html();
        $t.unwrap();
        return content;
    }
};
42
Tokimon

Pour être vraiment jQuery-esque, vous voudrez peut-être que outerHTML() soit un getter and _ et un comportement aussi semblable que possible à html():

$.fn.outerHTML = function (arg) {
    var ret;

    // If no items in the collection, return
    if (!this.length)
        return typeof arg == "undefined" ? this : null;
    // Getter overload (no argument passed)
    if (!arg) {
        return this[0].outerHTML || 
            (ret = this.wrap('<div>').parent().html(), this.unwrap(), ret);
    }
    // Setter overload
    $.each(this, function (i, el) {
        var fnRet, 
            pass = el,
            inOrOut = el.outerHTML ? "outerHTML" : "innerHTML";

        if (!el.outerHTML)
            el = $(el).wrap('<div>').parent()[0];

        if (jQuery.isFunction(arg)) { 
            if ((fnRet = arg.call(pass, i, el[inOrOut])) !== false)
                el[inOrOut] = fnRet;
        }
        else
            el[inOrOut] = arg;

        if (!el.outerHTML)
            $(el).children().unwrap();
    });

    return this;
}

Démo de travail: http://jsfiddle.net/AndyE/WLKAa/

Cela nous permet de passer un argument à outerHTML, qui peut être 

  • une fonction annulable - function (index, oldOuterHTML) { } - où la valeur de retour deviendra le nouveau code HTML de l'élément (sauf si false est renvoyé).
  • une chaîne, qui sera définie à la place du code HTML de chaque élément. 

Pour plus d'informations, voir la documentation jQuery pour html() .

18
Andy E

Vous pouvez également utiliser get (Récupérer les éléments DOM mis en correspondance par l’objet jQuery.).

par exemple:

$('div').get(0).outerHTML;//return "<div></div>"

Comme méthode d'extension:

jQuery.fn.outerHTML = function () {
  return this.get().map(function (v) {
    return v.outerHTML
  }).join()
};

Ou

jQuery.fn.outerHTML = function () {
  return $.map(this.get(), function (v) {
    return v.outerHTML
  }).join()
};

Choix multiple et retourne le code HTML externe de tous les éléments correspondants.

$('input').outerHTML()

revenir:

'<input id="input1" type="text"><input id="input2" type="text">'
14
MJ Vakili

Pour créer un plugin jQuery COMPLET en .outerHTML, ajoutez le script suivant à tout fichier js et incluez après jQuery dans votre en-tête:

mettre à jour La nouvelle version offre un meilleur contrôle ainsi qu'un service plus convivial pour jQuery Selector! :)

;(function($) {
    $.extend({
        outerHTML: function() {
            var $ele = arguments[0],
                args = Array.prototype.slice.call(arguments, 1)
            if ($ele && !($ele instanceof jQuery) && (typeof $ele == 'string' || $ele instanceof HTMLCollection || $ele instanceof Array)) $ele = $($ele);
            if ($ele.length) {
                if ($ele.length == 1) return $ele[0].outerHTML;
                else return $.map($("div"), function(ele,i) { return ele.outerHTML; });
            }
            throw new Error("Invalid Selector");
        }
    })
    $.fn.extend({
        outerHTML: function() {
            var args = [this];
            if (arguments.length) for (x in arguments) args.Push(arguments[x]);
            return $.outerHTML.apply($, args);
        }
    });
})(jQuery);

Cela vous permettra non seulement d’obtenir la couche HTML externe d’un élément, mais également d’obtenir un retour Array de plusieurs éléments à la fois! et peut être utilisé dans les deux styles standard jQuery en tant que tel:

$.outerHTML($("#eleID")); // will return outerHTML of that element and is 
// same as
$("#eleID").outerHTML();
// or
$.outerHTML("#eleID");
// or
$.outerHTML(document.getElementById("eleID"));

Pour plusieurs éléments

$("#firstEle, .someElesByClassname, tag").outerHTML();

Exemples d'extraits:

console.log('$.outerHTML($("#eleID"))'+"\t", $.outerHTML($("#eleID"))); 
console.log('$("#eleID").outerHTML()'+"\t\t", $("#eleID").outerHTML());
console.log('$("#firstEle, .someElesByClassname, tag").outerHTML()'+"\t", $("#firstEle, .someElesByClassname, tag").outerHTML());

var checkThisOut = $("div").outerHTML();
console.log('var checkThisOut = $("div").outerHTML();'+"\t\t", checkThisOut);
$.each(checkThisOut, function(i, str){ $("div").eq(i).text("My outerHTML Was: " + str); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://rawgit.com/JDMcKinstry/ce699e82c7e07d02bae82e642fb4275f/raw/deabd0663adf0d12f389ddc03786468af4033ad2/jQuery.outerHTML.js"></script>
<div id="eleID">This will</div>
<div id="firstEle">be Replaced</div>
<div class="someElesByClassname">At RunTime</div>
<h3><tag>Open Console to see results</tag></h3>

10
SpYk3HH

vous pouvez aussi le faire de cette façon

document.getElementById(id).outerHTML

où id est l'identifiant de l'élément que vous recherchez

8
Andy

J'ai utilisé la solution de Jessica (qui a été éditée par Josh) pour que outerHTML fonctionne avec Firefox. Le problème cependant, c'est que mon code était en train de s'effriter car sa solution englobait l'élément dans une DIV. L'ajout d'une ligne de code supplémentaire a résolu ce problème.

Le code suivant vous donne le fichier outerHTML en laissant l’arborescence DOM inchangée.

$jq.fn.outerHTML = function() {
    if ($jq(this).attr('outerHTML'))
        return $jq(this).attr('outerHTML');
    else
    {
    var content = $jq(this).wrap('<div></div>').parent().html();
        $jq(this).unwrap();
        return content;
    }
}

Et utilisez-le comme ceci: $ ("# myDiv"). OuterHTML ();

J'espère que quelqu'un le trouvera utile!

6
Arpan Dhandhania
// no cloning necessary    
var x = $('#xxx').wrapAll('<div></div>').parent().html(); 
alert(x);

Violon ici: http://jsfiddle.net/ezmilhouse/Mv76a/

5
Abdennour TOUMI

Si le scénario ajoute une nouvelle ligne de manière dynamique, vous pouvez utiliser ceci:

var row = $(".myRow").last().clone();
$(".myRow").last().after(row);

.myrow est le nom de classe du <tr>. Il crée une copie de la dernière ligne et l'insère en tant que nouvelle dernière ligne . Cela fonctionne également dans IE7 , alors que la méthode [0].outerHTML n'autorise pas les affectations dans ie7

3
Stefan Bookholt

Vous pouvez trouver une bonne option .outerHTML () ici https://github.com/darlesson/jquery-outerhtml .

Contrairement à .html () qui renvoie uniquement le contenu HTML de l'élément, cette version de .outerHTML () renvoie l'élément sélectionné et son contenu HTML ou le remplace en tant que méthode .replaceWith (), mais à la différence qui permet au code HTML de remplacement d'hériter le chaînage.

Des exemples peuvent également être vus dans l'URL ci-dessus.

2
Darlesson

Une autre solution similaire avec l'ajout de remove() de l'objet DOM temporaire.

2
Chris

J'ai utilisé la solution de Volomike mise à jour par Jessica. Je viens juste d'ajouter une vérification pour voir si l'élément existe et l'a renvoyé en blanc au cas où il ne l'aurait pas.

jQuery.fn.outerHTML = function() {
return $(this).length > 0 ? $(this).clone().wrap('<div />').parent().html() : '';
};

Bien sûr, utilisez-le comme:

$('table#buttons').outerHTML();
2
Ivan Chaer

J'ai fait ce test simple avec outerHTML étant la solution tokimon (sans clone), et outerHTML2 étant la solution Jessica (clone)

console.time("outerHTML");
for(i=0;i<1000;i++)
 {                 
  var html = $("<span style='padding:50px; margin:50px; display:block'><input type='text' title='test' /></span>").outerHTML();
 }                 
console.timeEnd("outerHTML");

console.time("outerHTML2");

 for(i=0;i<1000;i++)
 {                 
   var html = $("<span style='padding:50px; margin:50px; display:block'><input type='text' title='test' /></span>").outerHTML2();
  }                 
  console.timeEnd("outerHTML2");

et le résultat dans mon navigateur chrome (version 20.0.1132.57 (0)) était 

outerHTML: 81ms
outerHTML2: 439ms

mais si nous utilisons la solution tokimon sans la fonction native outerHTML (qui est maintenant prise en charge dans presque tous les navigateurs)

on a

outerHTML: 594ms
outerHTML2: 332ms 

et il y aura plus de boucles et d'éléments dans des exemples réels, de sorte que la combinaison parfaite serait

$.fn.outerHTML = function() 
{
  $t = $(this);
  if( "outerHTML" in $t[0] ) return $t[0].outerHTML; 
  else return $t.clone().wrap('<p>').parent().html(); 
}

alors la méthode de clonage est en réalité plus rapide que la méthode de bouclage/déroulage
(jquery 1.7.2)

2
Petar

Voici un plugin outerHTML très optimisé pour jQuery: ( http://jsperf.com/outerhtml-vs-jquery-clone-hack/5 > les 2 autres extraits de code rapides ne sont pas compatibles avec certains des navigateurs comme FF <11)

(function($) {

  var DIV = document.createElement("div"),
      outerHTML;

  if ('outerHTML' in DIV) {
    outerHTML = function(node) {
      return node.outerHTML;
    };
  } else {
    outerHTML = function(node) {
      var div = DIV.cloneNode();
      div.appendChild(node.cloneNode(true));
      return div.innerHTML;
    };
  }

  $.fn.outerHTML = function() {
    return this.length ? outerHTML(this[0]) : void(0);
  };

})(jQuery);

@Andy E => Je ne suis pas d'accord avec toi. outerHMTL n'a pas besoin de getter ET de setter: jQuery nous donne déjà 'replaceWith' ...

@mindplay => Pourquoi rejoignez-vous tous les outerHTML? jquery.html renvoie uniquement le contenu HTML de l'élément FIRST.

(Désolé, je n'ai pas assez de réputation pour écrire des commentaires)

2
gtournie

Notez que la solution de Josh ne fonctionne que pour un seul élément.

On peut soutenir que le code HTML "externe" n'a de sens que si vous avez un seul élément, mais il existe des situations où il est judicieux de transformer une liste d'éléments HTML en un balisage.

En prolongeant la solution de Josh, celle-ci gérera plusieurs éléments:

(function($) {
  $.fn.outerHTML = function() {
    var $this = $(this);
    if ($this.length>1)
      return $.map($this, function(el){ return $(el).outerHTML(); }).join('');
    return $this.clone().wrap('<div/>').parent().html();
  }
})(jQuery);

Edit: un autre problème avec la solution de Josh résolu, voir le commentaire ci-dessus.

2
mindplay.dk

node.cloneNode () ne semble guère être un hack. Vous pouvez cloner le nœud et l'ajouter à n'importe quel élément parent souhaité, mais aussi le manipuler en manipulant des propriétés individuelles, plutôt que d'avoir à le faire, par exemple. exécuter des expressions régulières sur celui-ci, ou l'ajouter dans le DOM, puis le manipuler après les mots.

Cela dit, vous pouvez également parcourir les attributs de l'élément pour en construire une représentation sous forme de chaîne HTML. Il semble probable que c'est de cette manière que n'importe quelle fonction outerHTML serait implémentée si jQuery en ajoutait une.

2
Ben Regenspan

C'est très bien pour changer les éléments sur le dom mais ne fonctionne PAS pour, par exemple, quand on passe une chaîne html dans jquery comme ceci:

$('<div id="foo">Some <span id="blog">content</span></div>').find('#blog').outerHTML();

Après quelques manipulations, j'ai créé une fonction qui permet à ce qui précède de fonctionner, par exemple pour les chaînes html:

$.fn.htmlStringOuterHTML = function() {     
    this.parent().find(this).wrap('<div/>');        
    return this.parent().html();
};
1
inspiraller

Court et doux.

[].reduce($('.x'), function(i,v) {return i+v.outerHTML}, '')

ou événement plus doux avec l'aide des fonctions de flèche

[].reduce.call($('.x'), (i,v) => i+v.outerHTML, '')

ou sans jQuery du tout

[].reduce.call(document.querySelectorAll('.x'), (i,v) => i+v.outerHTML, '')

ou si vous n'aimez pas cette approche, vérifiez que

$('.x').get().reduce((i,v) => i+v.outerHTML, '')
1
rolacja

C'est assez simple avec JavaScript vanille ...

document.querySelector('#selector')
1
Holly

le plugin jQuery est un raccourci pour obtenir directement l'élément HTML entier:

jQuery.fn.outerHTML = function () {
    return jQuery('<div />').append(this.eq(0).clone()).html();
};

Et utilisez-le comme ceci: $(".element").outerHTML();

0
Sky Yip

Je suis tombé sur cette question en cherchant une réponse à mon problème: j'essayais de supprimer une ligne de table, puis de la rajouter au bas de la table (car je créais de manière dynamique des lignes de données, mais je voulais afficher un message 'Add New Enregistrer le type de ligne en bas).

J'ai eu le même problème, en ce sens qu'il renvoyait le innerHtml et qu'il manquait les balises TR, qui contenaient l'ID de cette ligne et signifiait qu'il était impossible de répéter la procédure.

La réponse que j’ai trouvée est que la fonction jquery remove() renvoie en fait l’élément qu’elle supprime en tant qu’objet. Donc, pour supprimer et rajouter une ligne, c'était aussi simple que cela ...

var a = $("#trRowToRemove").remove();            
$('#tblMyTable').append(a);  

Si vous ne supprimez pas l'objet mais souhaitez le copier ailleurs, utilisez plutôt la fonction clone().

0
fishy