Get selected element's outer HTML

Jquery

Jquery Problem Overview


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?

Jquery Solutions


Solution 1 - Jquery

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

Solution 2 - Jquery

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.

Solution 3 - Jquery

2014 Edit : The question and this reply are from 2010. At the time, no better solution was widely available. Now, many of the other replies are better : Eric Hu's, or Re Capcha's for example.

This site seems to have a solution for you : jQuery: outerHTML | Yelotofu

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

Solution 4 - Jquery

What about: prop('outerHTML')?

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

And to set:

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

It worked for me.

PS: This is added in jQuery 1.6.

Solution 5 - Jquery

Extend jQuery:

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

And use it like this: $("#myTableRow").outerHTML();

Solution 6 - Jquery

I agree with Arpan (Dec 13 '10 5:59).

His way of doing it is actually a MUCH better way of doing it, as you dont use clone. The clone method is very time consuming, if you have child elements, and nobody else seemed to care that IE actually HAVE the outerHTML attribute (yes IE actually have SOME useful tricks up its sleeve).

But I would probably create his script a bit different:

$.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;
    }
};

Solution 7 - Jquery

To be truly jQuery-esque, you might want outerHTML() to be a getter and a setter and have its behaviour as similar to html() as possible:

$.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;
}

>Working demo: http://jsfiddle.net/AndyE/WLKAa/</b>

This allows us to pass an argument to outerHTML, which can be

  • a cancellable function — function (index, oldOuterHTML) { } — where the return value will become the new HTML for the element (unless false is returned).
  • a string, which will be set in place of the HTML of each element.

For more information, see the jQuery docs for html().

Solution 8 - Jquery

You can also use get (Retrieve the DOM elements matched by the jQuery object.).

e.g:

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

As extension method :

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

Or

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

Multiple choice and return the outer html of all matched elements.

$('input').outerHTML()

return:

'<input id="input1" type="text"><input id="input2" type="text">'

Solution 9 - Jquery

To make a FULL jQuery plugin as .outerHTML, add the following script to any js file and include after jQuery in your header:

> update New version has better control as well as a more jQuery Selector friendly service! :)

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

This will allow you to not only get the outerHTML of one element, but even get an Array return of multiple elements at once! and can be used in both jQuery standard styles as such:

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

For multiple elements

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

#Snippet Examples:

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>

Solution 10 - Jquery

you can also just do it this way

document.getElementById(id).outerHTML

where id is the id of the element that you are looking for

Solution 11 - Jquery

I used Jessica's solution (which was edited by Josh) to get outerHTML to work on Firefox. The problem however is that my code was breaking because her solution wrapped the element into a DIV. Adding one more line of code solved that problem.

The following code gives you the outerHTML leaving the DOM tree unchanged.

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

And use it like this: $("#myDiv").outerHTML();

Hope someone finds it useful!

Solution 12 - Jquery

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

Fiddle here: http://jsfiddle.net/ezmilhouse/Mv76a/

Solution 13 - Jquery

If the scenario is appending a new row dynamically, you can use this:

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

.myrow is the classname of the <tr>. It makes a copy of the last row and inserts that as a new last row. This also works in IE7, while the [0].outerHTML method does not allow assignments in ie7

Solution 14 - Jquery

node.cloneNode() hardly seems like a hack. You can clone the node and append it to any desired parent element, and also manipulate it by manipulating individual properties, rather than having to e.g. run regular expressions on it, or add it in to the DOM, then manipulate it afterwords.

That said, you could also iterate over the attributes of the element to construct an HTML string representation of it. It seems likely this is how any outerHTML function would be implemented were jQuery to add one.

Solution 15 - Jquery

You can find a good .outerHTML() option here https://github.com/darlesson/jquery-outerhtml.

Unlike .html() that returns only the element's HTML content, this version of .outerHTML() returns the selected element and its HTML content or replaces it as .replaceWith() method but with the difference that allows the replacing HTML to be inherit by the chaining.

Examples can also be seeing in the URL above.

Solution 16 - Jquery

I've used Volomike's solution updated by Jessica. Just added a check to see if the element exists, and made it return blank in case it doesn't.

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

Of course, use it like:

$('table#buttons').outerHTML();

Solution 17 - Jquery

This is quite simple with vanilla JavaScript...

document.querySelector('#selector')

Solution 18 - Jquery

Note that Josh's solution only works for a single element.

Arguably, "outer" HTML only really makes sense when you have a single element, but there are situations where it makes sense to take a list of HTML elements and turn them into markup.

Extending Josh's solution, this one will handle multiple elements:

(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: another problem with Josh's solution fixed, see comment above.

Solution 19 - Jquery

Anothe similar solution with added remove() of the temporary DOM object.

Solution 20 - Jquery

I have made this simple test with outerHTML being tokimon solution (without clone), and outerHTML2 being jessica solution (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");

and the result in my chromium (Version 20.0.1132.57 (0)) browser was

outerHTML: 81ms
outerHTML2: 439ms

but if we use tokimon solution without the native outerHTML function (which is now supported in probably almost every browser)

we get

outerHTML: 594ms
outerHTML2: 332ms

and there are gonna be more loops and elements in real world examples, so the perfect combination would be

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

so clone method is actually faster than wrap/unwrap method
(jquery 1.7.2)

Solution 21 - Jquery

Here is a very optimized outerHTML plugin for jquery: (http://jsperf.com/outerhtml-vs-jquery-clone-hack/5 => the 2 others fast code snippets are not compatible with some browsers like 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 => I don't agree with you. outerHMTL doesn't need a getter AND a setter: jQuery already give us 'replaceWith'...

@mindplay => Why are you joining all outerHTML? jquery.html return only the HTML content of the FIRST element.

(Sorry, don't have enough reputation to write comments)

Solution 22 - Jquery

Short and sweet.

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

or event more sweet with help of arrow functions

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

or without jQuery at all

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

or if you don't like this approach, check that

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

Solution 23 - Jquery

This is great for changing elements on the dom but does NOT work for ie when passing in a html string into jquery like this:

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

After some manipulation I have created a function which allows the above to work in ie for html strings:

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

Solution 24 - Jquery

$.html = el => $("<div>"+el+"</div>").html().trim();

Solution 25 - Jquery

I came across this while looking for an answer to my issue which was that I was trying to remove a table row then add it back in at the bottom of the table (because I was dynamically creating data rows but wanted to show an 'Add New Record' type row at the bottom).

I had the same issue, in that it was returning the innerHtml so was missing the TR tags, which held the ID of that row and meant it was impossible to repeat the procedure.

The answer I found was that the jquery remove() function actually returns the element, that it removes, as an object. So, to remove and re-add a row it was as simple as this...

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

If you're not removing the object but want to copy it somewhere else, use the clone() function instead.

Solution 26 - Jquery

jQuery plugin as a shorthand to directly get the whole element HTML:

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

And use it like this: $(".element").outerHTML();

Solution 27 - Jquery

Pure JavaScript:

var outerHTML = function(node) {
  var div = document.createElement("div");
  div.appendChild(node.cloneNode(true));
  return div.innerHTML;
};

Solution 28 - Jquery

$("#myNode").parent(x).html(); 

Where 'x' is the node number, beginning with 0 as the first one, should get the right node you want, if you're trying to get a specific one. If you have child nodes, you should really be putting an ID on the one you want, though, to just zero in on that one. Using that methodology and no 'x' worked fine for me.

Solution 29 - Jquery

Simple solution.

var myself = $('#div').children().parent();

Solution 30 - Jquery

$("#myTable").parent().html();

Perhaps I'm not understanding your question properly, but this will get the selected element's parent element's html.

Is that what you're after?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRyanView Question on Stackoverflow
Solution 1 - JqueryEric HuView Answer on Stackoverflow
Solution 2 - JqueryVolomikeView Answer on Stackoverflow
Solution 3 - JqueryDavid V.View Answer on Stackoverflow
Solution 4 - JqueryRe CaptchaView Answer on Stackoverflow
Solution 5 - JqueryjessicaView Answer on Stackoverflow
Solution 6 - JqueryTokimonView Answer on Stackoverflow
Solution 7 - JqueryAndy EView Answer on Stackoverflow
Solution 8 - JqueryMJ VakiliView Answer on Stackoverflow
Solution 9 - JquerySpYk3HHView Answer on Stackoverflow
Solution 10 - JqueryAndyView Answer on Stackoverflow
Solution 11 - JqueryArpan DhandhaniaView Answer on Stackoverflow
Solution 12 - JqueryAbdennour TOUMIView Answer on Stackoverflow
Solution 13 - JqueryStefan BookholtView Answer on Stackoverflow
Solution 14 - JqueryBen RegenspanView Answer on Stackoverflow
Solution 15 - JqueryDarlessonView Answer on Stackoverflow
Solution 16 - JqueryIvan ChaerView Answer on Stackoverflow
Solution 17 - JqueryHollyView Answer on Stackoverflow
Solution 18 - Jquerymindplay.dkView Answer on Stackoverflow
Solution 19 - JqueryChrisView Answer on Stackoverflow
Solution 20 - JqueryPetarView Answer on Stackoverflow
Solution 21 - JquerygtournieView Answer on Stackoverflow
Solution 22 - JqueryrolacjaView Answer on Stackoverflow
Solution 23 - JqueryinspirallerView Answer on Stackoverflow
Solution 24 - JqueryevandrixView Answer on Stackoverflow
Solution 25 - JqueryfishyView Answer on Stackoverflow
Solution 26 - JquerySky YipView Answer on Stackoverflow
Solution 27 - JqueryRehmatView Answer on Stackoverflow
Solution 28 - JqueryvapcguyView Answer on Stackoverflow
Solution 29 - JqueryZeeshanView Answer on Stackoverflow
Solution 30 - JquerybrettkellyView Answer on Stackoverflow