From 173c1477ae6efc4c2eeb7131ba0646c4e1323975 Mon Sep 17 00:00:00 2001 From: John Resig Date: Mon, 14 Sep 2009 22:09:42 +0000 Subject: [PATCH] Added support for .before(), .after(), and .replaceWith() on disconnected DOM nodes. Fixes bug #3940. --- src/manipulation.js | 32 +++++++++++++++++++++++++------- test/unit/manipulation.js | 18 +++++++++++++++--- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/manipulation.js b/src/manipulation.js index 5013838..4746dc8 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -106,15 +106,29 @@ jQuery.fn.extend({ }, before: function() { - return this.domManip(arguments, false, function(elem){ - this.parentNode.insertBefore( elem, this ); - }); + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function(elem){ + this.parentNode.insertBefore( elem, this ); + }); + } else { + var set = jQuery.isFunction(arguments[0]) ? + jQuery( arguments[0]() ) : + jQuery.apply(jQuery, arguments); + + return this.pushStack( set.add( this ), "before", arguments ); + } }, after: function() { - return this.domManip(arguments, false, function(elem){ - this.parentNode.insertBefore( elem, this.nextSibling ); - }); + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function(elem){ + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + } else { + return jQuery.isFunction(arguments[0]) ? + this.add( arguments[0]() ) : + this.add.apply( this, arguments ); + } }, clone: function( events ) { @@ -193,7 +207,11 @@ jQuery.fn.extend({ }, replaceWith: function( value ) { - return this.after( value ).remove(); + if ( this[0] && this[0].parentNode ) { + return this.after( value ).remove(); + } else { + return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ); + } }, detach: function( selector ) { diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 49d717f..465686f 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -320,7 +320,7 @@ test("prependTo(String|Element|Array<Element>|jQuery)", function() { }); var testBefore = function(val) { - expect(4); + expect(6); var expected = 'This is a normal link: bugaYahoo'; jQuery('#yahoo').before(val( 'buga' )); equals( expected, jQuery('#en').text(), 'Insert String before' ); @@ -339,6 +339,10 @@ var testBefore = function(val) { expected = "This is a normal link: diveintomarkTry them out:Yahoo"; jQuery('#yahoo').before(val( jQuery("#first, #mark") )); equals( expected, jQuery('#en').text(), "Insert jQuery before" ); + + var set = jQuery("
").before(val("test")); + equals( set[0].nodeName.toLowerCase(), "span", "Insert the element before the disconnected node." ); + equals( set.length, 2, "Insert the element before the disconnected node." ); } test("before(String|Element|Array<Element>|jQuery)", function() { @@ -372,7 +376,7 @@ test("insertBefore(String|Element|Array<Element>|jQuery)", function() { }); var testAfter = function(val) { - expect(4); + expect(6); var expected = 'This is a normal link: Yahoobuga'; jQuery('#yahoo').after(val( 'buga' )); equals( expected, jQuery('#en').text(), 'Insert String after' ); @@ -391,6 +395,10 @@ var testAfter = function(val) { expected = "This is a normal link: YahoodiveintomarkTry them out:"; jQuery('#yahoo').after(val( jQuery("#first, #mark") )); equals( expected, jQuery('#en').text(), "Insert jQuery after" ); + + var set = jQuery("
").after(val("test")); + equals( set[1].nodeName.toLowerCase(), "span", "Insert the element after the disconnected node." ); + equals( set.length, 2, "Insert the element after the disconnected node." ); }; test("after(String|Element|Array<Element>|jQuery)", function() { @@ -424,7 +432,7 @@ test("insertAfter(String|Element|Array<Element>|jQuery)", function() { }); var testReplaceWith = function(val) { - expect(10); + expect(12); jQuery('#yahoo').replaceWith(val( 'buga' )); ok( jQuery("#replace")[0], 'Replace element with string' ); ok( !jQuery("#yahoo")[0], 'Verify that original element is gone, after string' ); @@ -445,6 +453,10 @@ var testReplaceWith = function(val) { ok( jQuery("#first")[0], 'Replace element with set of elements' ); ok( jQuery("#mark")[0], 'Replace element with set of elements' ); ok( !jQuery("#yahoo")[0], 'Verify that original element is gone, after set of elements' ); + + var set = jQuery("
").replaceWith(val("test")); + equals( set[0].nodeName.toLowerCase(), "span", "Replace the disconnected node." ); + equals( set.length, 1, "Replace the disconnected node." ); } test("replaceWith(String|Element|Array<Element>|jQuery)", function() { -- 1.7.10.4