Li Haoyi
Li Haoyi

Reputation: 15802

JQuery: elegant way to replace set of elements with another set?

I have a bunch of DOM like

<div>
    <div class="stuff"/>
    <div class="stuff"/>
    <div class="stuff"/>
</div>

and I want to replace it with a new set of stuff

<div>
    <div class="stuff"/>
    <p class="stuff"/>
    <ul class="stuff"/>
    <a class="stuff"/>
</div>

Which will be fetched via Ajax. My question is: what is the best way to do this?

$.replaceWith doesn't quite do what I want, because I then end up with multiple copies of the new stuff.

I can guarantee that all the stuff will be in one contiguous block, and so presumably I could put in some placeholder after the last element (or before the first element) of the old stuff, remove the old stuff, and replace the placeholder with the new stuff.

However, this seems rather roundabout and inelegant. Is there any clever way of, removing all the old stuff and putting in a single copy of the new stuff, all at one go?

EDIT: I would also like to do this without using any container divs. Using container divs would work in the above case, but would fail in some cases, like when the stuff is inside a <table>:

<table>
    <head/>
    <body>
        <tr/>
        <tr class="stuff"/>
        <tr class="stuff"/>
        <tr class="stuff"/>
        <tr/>
    </body>
</table>

If i want to replace the rows labelled stuff with another set of rows, possibly more, possibly fewer, there is no way I can nicely put them in a container thingy without breaking the HTML, since the <body> can only contain <tr>s (IIRC).

Upvotes: 9

Views: 3686

Answers (3)

Alnitak
Alnitak

Reputation: 339816

$('#outerdiv').empty().append(newContent);

Unlike .html(), this will work regardless of whether newContent is an HTML string, or an existing DOM structure.

If there are multiple elements to be replaced but where you need to retain their siblings, you can do this:

$('.stuff').first().before(newContent).end().remove();

i.e. take the first .stuff element, add the new content before it, and then remove all the .stuff elements.

Upvotes: 13

lonesomeday
lonesomeday

Reputation: 237865

One way to do it would be with wrapAll:

$('.stuff').wrapAll('<div/>').parent().replaceWith('<div class="stuff"/>');

I'm not sure if that passes the "elegant" test, but it does work regardless of whether there is any other content in the containing element.

With that said, though, this seems to be a very complicated solution to a simple problem. The simple solution would be to wrap your elements in a containing element; this shouldn't be a problem if, as you say, you can guarantee that they will always be together.

Upvotes: 4

Diodeus - James MacFarlane
Diodeus - James MacFarlane

Reputation: 114367

Yes: $('#tagetDiv').html(newContent)

Upvotes: 3

Related Questions