3

I'm trying to use replaceWith(...) function with a jQuery Object but it does not work, when i try do it with inserted DOM elements it works, but not in jQuery objects.

I have this:

var obj = $('<div id="obj">Text</div>');
obj.replaceWith('<span>New text</span>');

"obj" is not replaced with the new HTML.

Here is the demo: http://jsfiddle.net/v7EA2/

Maybe i did not understand how replaceWith() function works,

Thanks by your help.


UPDATE

Please look at here: http://jsfiddle.net/v7EA2/6/

calbertts
  • 1,513
  • 2
  • 15
  • 34
  • If you are trying to replace and element in the DOM with another, you must select it first and then call .replaceWith() . In your example, you are creating a new element that does not exist in the DOM. Explain what you are trying to do exactly. – pmandell Dec 16 '13 at 16:53
  • Please tell us expected result! – A. Wolff Dec 16 '13 at 16:54
  • I'm trying replace an element before insert it on DOM. – calbertts Dec 16 '13 at 16:55

3 Answers3

4

It happens because your element does not have a parent. Append it to the DOM or to another jQuery collection and it will work.

I created a little demo that might help in understanding what this method does.

DETAILS:

I will sum up the research that is detailed in the comments below this answer. Thanks to PSL, calberts, Jason P and A. Wolff.

  1. The documentation of replaceWith states the following:

    As of jQuery 1.4, .replaceWith() can also work on disconnected DOM nodes. For example, with the following code, .replaceWith() returns a jQuery set containing only a paragraph.:

    $( "<div/>" ).replaceWith("<p></p>" );

  2. This means that the example provided by the OP should indeed work. And it works till version 1.8. Unfortunately, from version 1.9 it stops working. This seemed to be a bug and only happens if you are trying to replace the "root element" of the jQuery object.

  3. Actually the change in 1.9 was documented:

    Prior to 1.9, .after(), .before(), and .replaceWith() would attempt to add or change nodes in the current jQuery set if the first node in the set was not connected to a document, and in those cases return a new jQuery set rather than the original set. This created several inconsistencies and outright bugs--the method might or might not return a new result depending on its arguments! As of 1.9, these methods always return the original unmodified set and attempting to use .after(), .before(), or .replaceWith() on a node without a parent has no effect--that is, neither the set or the nodes it contains are changed.

    Problem is that the change never made it to the official docs. I found a bug posted about this, but it was closed because it belongs to a different tracker.


Quick Solution:

In the OP's situation, the easiest way to "replace" the element would be

var obj = $('<div id="obj">Text</div>');
obj = $('<span>New text</span>');

but only if it is not in the DOM yet :).

kapa
  • 77,694
  • 21
  • 158
  • 175
  • Actually [doc says](http://api.jquery.com/replaceWith/) `As of jQuery 1.4, .replaceWith() can also work on disconnected DOM nodes. For example, with the following code, .replaceWith() returns a jQuery set containing only a paragraph.:` `$( "
    " ).replaceWith( "

    " );`
    – PSL Dec 16 '13 at 16:57
  • @PSL That is true, but the `obj` variable will still store the div, unless you update it with the return value of the `replaceWith` method. – kapa Dec 16 '13 at 16:59
  • No that doesn't work either, seems like a bug to me... Even according to the example provided in the doc it should work. Yeah try other way around as well. It doesn't – PSL Dec 16 '13 at 17:00
  • @PSL It is not a bug. The docs never state that the variable will be updated. Only the return value will be the new element. – kapa Dec 16 '13 at 17:00
  • 2
    But see this: http://jsfiddle.net/v7EA2/6/ If i try selecting something inside element, it works!! – calbertts Dec 16 '13 at 17:01
  • 2
    `$( "
    " ).replaceWith( "

    " );` should return a `p` tag but it doesnt
    – PSL Dec 16 '13 at 17:01
  • 1
    @:kapa But looking at the example provided by @calbertts, it works but not on root nodes. So considering the documentation this seems like a bug. – PSL Dec 16 '13 at 17:05
  • 2
    @PSL These two statements in the docs seem contradictory: _"The .replaceWith() method, like most jQuery methods, returns the jQuery object so that other methods can be chained onto it. However, it must be noted that the original jQuery object is returned. This object refers to the element that has been removed from the DOM, not the new element that has replaced it._" and _"As of jQuery 1.4, .replaceWith() can also work on disconnected DOM nodes. For example, with the following code, .replaceWith() returns a jQuery set containing only a paragraph.:"_ `$( "
    " ).replaceWith( "

    " );`
    – Jason P Dec 16 '13 at 17:05
  • 2
    @JasonP Yeah seems like it... :) Even the example they provided doesn't work. – PSL Dec 16 '13 at 17:06
  • 1
    @PSL the sample they provide works if we are talking about the same: http://jsfiddle.net/my89M/ See there, works too: http://jsfiddle.net/my89M/3/ – A. Wolff Dec 16 '13 at 17:13
  • 1
    @A.Wolff Something must have happened between 1.8 and 1.9 to change/break this: http://jsfiddle.net/cxxjZ/ – Jason P Dec 16 '13 at 17:15
  • @PSL my bad, ya so we can assume it is a bug – A. Wolff Dec 16 '13 at 17:15
  • Will you report this like a bug? – calbertts Dec 16 '13 at 18:23
  • @calbertts I made some further research and updated my answer. – kapa Dec 17 '13 at 12:01
3

Jsfillde: http://jsfiddle.net/v7EA2/3/

first make the DOM available and then change the html using $.replaceWith

var obj = $('<div>Text</div>');
$('#result').text(obj[0].outerHTML);
$('#result').replaceWith('<span>Text</span>');
patel.milanb
  • 5,822
  • 15
  • 56
  • 92
1

You can replace it before appending into the dom by the following code,

  var obj = $('<div>Text</div>').not('div').add('<span>New text</span>');

Theory : First you have to exclude the div from the intial Jquery object and then you have to add the new set of html into it.

DEMO

Rajaprabhu Aravindasamy
  • 66,513
  • 17
  • 101
  • 130
  • Well, seems there is a bug in newer jQuery versions with replaceWith(...) function, but your answer despite of not be more elegant or intuitive, works for me now. Thanks! – calbertts Dec 16 '13 at 18:27
  • 1
    Maybe I am missing something, but how is this different from simply updating the variable with `obj = $('New text')`? Seems overkill to me. – kapa Dec 17 '13 at 12:02