813

I'm trying to get the HTML of a selected object with jQuery. I am aware of the .html() function; the issue is that I need the HTML including the selected object (a table row in this case, where .html() only returns the cells inside the row).

I've searched around and found a few very ‘hackish’ type methods of cloning an object, adding it to a newly created div, etc, etc, but this seems really dirty. Is there any better way, or does the new version of jQuery (1.4.2) offer any kind of outerHtml functionality?

Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
Ryan
  • 17,511
  • 23
  • 63
  • 88

31 Answers31

698

I believe that currently (5/1/2012), all major browsers support the outerHTML function. It seems to me that this snippet is sufficient. I personally would choose to memorize this:

// 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: Basic support stats for element.outerHTML

Protector one
  • 6,926
  • 5
  • 62
  • 86
Eric Hu
  • 18,048
  • 9
  • 51
  • 67
  • 14
    @SalmanPK FireFox didn't support this property until 2011-11-11. https://bugzilla.mozilla.org/show_bug.cgi?id=92264 There are still a lot of users stuck on 3.6. I think this is actually a perfect example of why one would chose to use jQuery over native functionality. – Jeff Camera Jun 28 '12 at 16:38
  • 8
    @LuciferSam Firefox 3.6 has ~6% global market share according to gs.statcounter.com However, [filtering the results](http://gs.statcounter.com/#browser_version-US-monthly-201112-201205-bar) to the last 6 months (Dec '11-May '12) and to USA pushes it off their top 12 list (below 3%). I chose this window since [this article](http://www.maximumpc.com/article/news/advertised_update_leads_sharp_decline_firefox_36_usage) suggests FF 3.6 usage dropped significantly after Jan 2012. Given this data, I stand by my solution for simpler code over backwards compatibility. – Eric Hu Jun 28 '12 at 19:12
  • 4
    Couldn't agree more. This is the right answer here, not the other stuff people are suggesting. The element I select on has attributes I want to keep which are lost by the other answers. Hell, this even works in IE! – Matthew Bonig Aug 15 '12 at 19:22
  • No. Firefox 11 was not released until March 13, *2012* (fixed now), i.e. less than a year ago as of this writing. One of the benefits of jQuery is that it supports older browsers. I think supporting at least a year is reasonable, and some sites are obviously going to want more (remember, jQuery supports IE6). – Matthew Flaschen Jan 09 '13 at 02:50
  • Yep. This looks like the best answer I can see since there is no out of box jQuery equivalent. – Swanny Jan 30 '13 at 03:55
  • @EricHu Don't forget Firefox 4, 5, 6, 7, 8, 9, 10 and versions inbetween. – George Reith May 01 '13 at 15:00
  • @GeorgeReith FF 1-10 accounts for 1.53% of global market share as of Apr 2013, [source (manual adding required)](http://en.wikipedia.org/wiki/Template:Firefox_usage_share) – Eric Hu May 02 '13 at 07:09
  • 7
    @EricHu statcounter also states IE8 has 9.3% of the global browser share. Yet some of my websites are close to the 40% mark. It's all relative and varies enormously from website to website, Firefox 3.6 still accounts for roughly 10% on some of my websites. Global marketshare means nothing. It's all about your websites audience. – George Reith May 02 '13 at 08:10
  • A lot of people are commenting here about all the compatibilities issues around the .outerHTML function across the browsers. So I say the safe bet is to use the jQuery method described in other answers if you already use jQuery. It's a lot slower, but at least you have more guarantees of it working cross-platform. – Hoffmann Sep 04 '13 at 13:53
  • Random note but older Android does not supper outerHTML, you must use the append-clone-html method – ericjam Jan 06 '16 at 21:30
  • ** \*\*\* ** .outerHTML is a property, not a function :) – jave.web Mar 31 '16 at 10:33
  • The answer is sooo bad :) Can't see why it has so many upvotes, cause it doesn't solve the question. It doesn't return "selected elements" outerHTML, just "first selected element" outerHTML – rolacja Mar 02 '17 at 17:21
  • It seems this is not exactly a cross browser solution but using JQuery should guarantee you such. – Pavel Petrov Oct 17 '17 at 07:41
  • The last example looks off. "join()" uses a comma by default, which you don't want. I believe it should be: $('.classSelector').map(function(){return this.outerHTML}).get().join(""); – David Hammond Feb 08 '19 at 14:59
346

No need to generate a function for it. Just do it like this:

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

(Your browser's console will show what is logged, by the way. Most of the latest browsers since around 2009 have this feature.)

The magic is this on the end:

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

The clone means you're not actually disturbing the DOM. Run it without it and you'll see p tags inserted before/after all hyperlinks (in this example), which is undesirable. So, yes, use .clone().

The way it works is that it takes each a tag, makes a clone of it in RAM, wraps with p tags, gets the parent of it (meaning the p tag), and then gets the innerHTML property of it.

EDIT: Took advice and changed div tags to p tags because it's less typing and works the same.

philipvr
  • 5,738
  • 4
  • 32
  • 44
Volomike
  • 23,743
  • 21
  • 113
  • 209
  • 82
    I wonder why the jQuery team doesn't add a outerHtml() method? – Donny V. Jan 19 '12 at 14:11
  • What if the element is not `
    `?
    – Derek 朕會功夫 Mar 13 '12 at 00:15
  • 1
    @Derek, that wouldn't matter. I'm using DIV as a wrapper in order to get something inside it. – Volomike Mar 13 '12 at 22:13
  • 11
    .clone().wrap('

    ').parent().html(); is shorter

    – Uğur Gümüşhan Apr 01 '12 at 00:15
  • 1
    Yes, less keystrokes, and achieves the same effect. – Volomike Apr 04 '12 at 16:06
  • @Donny There's a big feature request ticket [here](http://bugs.jquery.com/ticket/8142) for it and some (bad) reasons for why they haven't added it. However the ticket remains closed for now. Any new people needing an outerHtml() function should post their use case in there and keep hassling them to add it into the jQuery core. We'll get it one day! – zuallauz Dec 04 '12 at 21:36
  • @PaulReinhardt, but many elements (all block elements) are not valid inside a `

    ` element. I haven't checked, but maybe JQuery prevents this operation (or will do so in the future) if the result is invalid.

    – Peter Herdenborg Dec 19 '12 at 08:59
  • 15
    Better to use DIV instead of P for a general solution -- not all elements can be wrapped in P as valid HTML. – Blazemonger May 31 '13 at 19:16
  • @Blazemonger nor in `div` – Gabriele Petrioli Oct 07 '13 at 18:07
  • Just a minor comment, if you happen to call this on the tag, you're going to have a bad time. (Don't even ask...) – user435779 Dec 19 '13 at 21:26
  • 1
    @Blazemonger - you are 100% correct. But using `

    ` should not cause any problem here. Because its just a temporary holder, not being added to the `DOM`. I think we can use use anything in `wrap`. Even `wrap('')` should do the trick.

    – shashwat Dec 25 '13 at 11:35
  • And for a list
  • -element this could come handy as for example ... $('.ul_element').prepend( $(this).clone().wrap('
  • ').parent().html() );
  • – K. Kilian Lindberg Feb 12 '14 at 00:22