Bug Tracker

Opened 11 years ago

Last modified 9 years ago

#8142 closed feature

outerhtml — at Version 19

Reported by: [email protected] Owned by:
Priority: low Milestone: 1.7
Component: manipulation Version: 1.5
Keywords: Cc:
Blocked by: Blocking:

Description (last modified by john)

As pointed out in the thread below, the outerhtml() method seems to be a standard feature expected by many, and it's missing.

http://stackoverflow.com/questions/2419749/jquery-get-selected-elements-outer-html

There's a solution for getting the outer HTML with jQuery posted in this thread - I'm not sure if it makes sense to provide a way to set the outer HTML, or how that would work.

Change History (19)

comment:1 Changed 11 years ago by Rick Waldron

Component: unfiledmanipulation
Owner: set to Rick Waldron
Priority: undecidedlow
Status: newassigned

In the spirit of jQuery.fn.width() having innerWidth and outerWidth variations, I think this is a good addition.

comment:2 Changed 11 years ago by jitter

I'm not convinced of the usefulness of this feature. Can you provide 2 or more use cases where this would be needed in "real life" applications.

Also the .outerHTML( newcontent ) is already available as .replaceWith( newcontent ).

And you should rarely be needing $(foo).outerHTML(), in most cases your probably want $(foo).clone()..... or $(foo).appendTo(...) or something like that.

Unless there is some really useful use case for this I'm missing, I guess we should stick to $(foo).eq(0).clone(true).wrap("<div></div>").html() or maybe provide this as a very small jQuery utility plugin

comment:3 Changed 11 years ago by mindplay

The use cases of outerhtml() are the same as for html(), only for cases where you want the markup of the container element itself. I'm sure I could provide many "real life" use cases where html() is useful, but I'm pretty sure none of those would be new to anyone.

One situation where outerhtml() would be preferable to html() is for cases where you need the markup of just one tag - typically end-nodes, like <img> tags for example. There's no direct way to do that at the moment.

Or in cases where you're dealing with multiple tags, for example a subset of list items, e.g. $('ul#users li.admin') which would include some of the children, but not all of them. In this case you can't simply clone and wrap, since you would be wrapping every individual child node.

I guess I would say, the value of this function is the same as most of the jQuery functions - most of them don't accomplish anything really fantastic that you couldn't do yourself with a few lines of code; the value is not having to write those few lines of code every time, and/or wondering which approach is most appropriate to accomplish what you want, with what you have.

In this case, you wouldn't need to worry or care whether you have one element or a list of elements - you just want the outer markup, as a string, without having to make decisions about which approach is best.

To me, that's the real value of jQuery - less time wasted on micro-management and trivial decision-making, since the jQuery functions handle most of the subtle variations of common tasks.

comment:4 Changed 11 years ago by jbasdf

I've needed an outerhtml() several times where the full string of the selected element was required. I've added a obj_to_s method to accomplish this, but it feels like it should be a part of jQuery. I add my vote to the feature.

comment:5 Changed 11 years ago by Justin Ball <[email protected]…>

Something else to consider if/when creating an outerhtml() method. The current technique involves using append which results in jQuery parsing out all script tags to have them executed. I have a situation where I don't want the script tags executed. Rather I just want the string that includes the script tags. Below are the relevant comments from this discussion: http://stackoverflow.com/questions/610995/jquery-cant-append-script-element

All of jQuery's insertion methods use a domManip function internally to clean/process elements before and after they are inserted into the DOM. One of the things the domManip function does is pull out any script elements about to be inserted and run them through an "evalScript routine" rather than inject them with the rest of the DOM fragment. It inserts the scripts separately, evaluates them, and then removes them from the DOM.

I believe that one of the reasons jQuery does this is to avoid "Permission Denied" errors that can occur in Internet Explorer when inserting scripts under certain circumstances. It also avoids repeatedly inserting/evaluating the same script (which could potentially cause problems) if it is within a containing element that you are inserting and then moving around the DOM.

comment:6 Changed 11 years ago by Justin Ball <[email protected]…>

comment:7 Changed 11 years ago by FlipScript

I second (or third) the request for .outerHTML (or similar).

On my web site, I need to swap out a Flash movie for another. The <embed> tag has no .html() [meaning, no innerHTML], and even if it did, the Flash movie doesn't update dynamically if the parameter is modified once it is seated.

However, the movie can be swapped out in all browsers by getting the HTML for the entire tag, changing the movie parameter, and putting the new object back in the original objects place.

So, this use case would be:

  1. The need for the entire element contents (.outerHTML)
  2. Modifying the elements contents
  3. Doing a .replaceWith() on the original element with the changed contents

.replaceWith replaces the entire element, but actually getting the contents of the entire element is not entirely intuitive.

comment:8 Changed 11 years ago by jboesch

Here's a quick jsfiddle of what outerHTML might look like if it were added to jQuery: http://jsfiddle.net/jboesch26/3SKsL/1/

comment:9 Changed 11 years ago by ajpiano

This comes up very regularly in IRC, a lot of people seem to have a need for it and there are several plugins that achieve this end. +1

Last edited 11 years ago by ajpiano (previous) (diff)

comment:10 Changed 11 years ago by john

Owner: Rick Waldron deleted
Status: assignedopen

So while it seems that people expect this, I tend to agree with jitter - the potential for abuse is simply enormous. So many people don't understand the concept of a DOM Element and think that they have to have the HTML to inject an element some place else. If we add outerHTML we're going to see a ton of stuff like: $("ul").append( $("#thing").outerHTML() );

Let's discuss this in the 1.7 Roadmap meeting.

comment:11 in reply to:  10 Changed 11 years ago by [email protected]

Gets my vote too. I've been bitten by this a few times as well, both with flash and table rows.

Replying to john:

(...) If we add outerHTML we're going to see a ton of stuff like: $("ul").append( $("#thing").outerHTML() );

Isn't it already possible to do this?

<div id="thing">
<li id="in-thing">blah...</li>
</div>
... 
$("ul").append( $("#thing").html() );

comment:12 Changed 11 years ago by timmywil

I'm also with jitter. In response to the last comment, yes that is possible, but $("ul").append( $("#thing") ) would work just fine without calling outerHTML(), hence the confusion.

comment:13 Changed 11 years ago by john

Keywords: 1.7-discuss added

Nominating ticket for 1.7 discussion.

comment:14 Changed 11 years ago by Rick Waldron

Description: modified (diff)

-1,

comment:15 Changed 11 years ago by jaubourg

-1, Official plugin with dom manipulation/selection helpers

comment:16 Changed 11 years ago by timmywil

+1, This is done too often. outerHTML could be used if available and give the user a performance boost over always appending to a disconnected node and calling html.

comment:17 Changed 11 years ago by dmethvin

Description: modified (diff)

+0, Not convinced it's needed, and not sure of the cost/effectiveness of an internal implementation. The clone/wrap seems like it could cause trouble with table component elements

comment:18 Changed 11 years ago by [email protected]

This would be useful. My use case is I am duplicating a table row and inserting it into a table at a specified row index. I guess I will have to wrap it in a div using clonedRow.wrap("<div></div>").html(). Even though I am cloning an element anyway, this is still not an obvious way to get the outerHTML, which is a standard thing you would expect jQuery would provide.

In some case you don't want to clone the element for perf reasons and it would be good to have a nicely optimised and cross browser way of doing this - exactly where you would hope jQuery would be able to help.

comment:19 Changed 11 years ago by john

Description: modified (diff)

-1, I fear that this will be abused by people not understanding what a DOM node is.

Note: See TracTickets for help on using tickets.