mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Manipulation: Detect sneaky no-content replaceWith input
Fixes gh-2204 Ref642e9a4557
Closes gh-1752 Closes gh-2206 (cherry picked from commit4b27ae16a2
) Conflicts: src/manipulation.js test/unit/manipulation.js
This commit is contained in:
parent
1e7a2f3674
commit
4cafb58ba4
@ -274,14 +274,13 @@ jQuery.extend({
|
|||||||
return clone;
|
return clone;
|
||||||
},
|
},
|
||||||
|
|
||||||
buildFragment: function( elems, context, scripts, selection ) {
|
buildFragment: function( elems, context, scripts, selection, ignored ) {
|
||||||
var j, elem, contains,
|
var j, elem, contains,
|
||||||
tmp, tag, wrap,
|
tmp, tag, wrap,
|
||||||
l = elems.length,
|
l = elems.length,
|
||||||
|
|
||||||
// Ensure a safe fragment
|
// Ensure a safe fragment
|
||||||
safe = createSafeFragment( context ),
|
safe = createSafeFragment( context ),
|
||||||
|
|
||||||
nodes = [],
|
nodes = [],
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
@ -343,9 +342,11 @@ jQuery.extend({
|
|||||||
i = 0;
|
i = 0;
|
||||||
while ( (elem = nodes[ i++ ]) ) {
|
while ( (elem = nodes[ i++ ]) ) {
|
||||||
|
|
||||||
// #4087 - If origin and destination elements are the same, and this is
|
// Skip elements already in the context collection (trac-4087)
|
||||||
// that element, do not do anything
|
|
||||||
if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
|
if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
|
||||||
|
if ( ignored ) {
|
||||||
|
ignored.push( elem );
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,28 +574,28 @@ jQuery.fn.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
replaceWith: function() {
|
replaceWith: function() {
|
||||||
var arg = arguments[ 0 ];
|
var ignored = [];
|
||||||
|
|
||||||
// Make the changes, replacing each context element with the new content
|
// Make the changes, replacing each non-ignored context element with the new content
|
||||||
this.domManip( arguments, function( elem ) {
|
return this.domManip( arguments, function( elem ) {
|
||||||
arg = this.parentNode;
|
var parent = this.parentNode;
|
||||||
|
|
||||||
|
if ( jQuery.inArray( this, ignored ) < 0 ) {
|
||||||
jQuery.cleanData( getAll( this ) );
|
jQuery.cleanData( getAll( this ) );
|
||||||
|
if ( parent ) {
|
||||||
if ( arg ) {
|
parent.replaceChild( elem, this );
|
||||||
arg.replaceChild( elem, this );
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Force removal if there was no new content (e.g., from empty arguments)
|
// Force callback invocation
|
||||||
return arg && (arg.length || arg.nodeType) ? this : this.remove();
|
}, ignored );
|
||||||
},
|
},
|
||||||
|
|
||||||
detach: function( selector ) {
|
detach: function( selector ) {
|
||||||
return this.remove( selector, true );
|
return this.remove( selector, true );
|
||||||
},
|
},
|
||||||
|
|
||||||
domManip: function( args, callback ) {
|
domManip: function( args, callback, ignored ) {
|
||||||
|
|
||||||
// Flatten any nested arrays
|
// Flatten any nested arrays
|
||||||
args = concat.apply( [], args );
|
args = concat.apply( [], args );
|
||||||
@ -617,19 +618,20 @@ jQuery.fn.extend({
|
|||||||
if ( isFunction ) {
|
if ( isFunction ) {
|
||||||
args[0] = value.call( this, index, self.html() );
|
args[0] = value.call( this, index, self.html() );
|
||||||
}
|
}
|
||||||
self.domManip( args, callback );
|
self.domManip( args, callback, ignored );
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( l ) {
|
if ( l ) {
|
||||||
fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
|
fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this, ignored );
|
||||||
first = fragment.firstChild;
|
first = fragment.firstChild;
|
||||||
|
|
||||||
if ( fragment.childNodes.length === 1 ) {
|
if ( fragment.childNodes.length === 1 ) {
|
||||||
fragment = first;
|
fragment = first;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( first ) {
|
// Require either new content or an interest in ignored elements to invoke the callback
|
||||||
|
if ( first || ignored ) {
|
||||||
scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
|
scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
|
||||||
hasScripts = scripts.length;
|
hasScripts = scripts.length;
|
||||||
|
|
||||||
|
@ -1329,15 +1329,20 @@ test( "replaceWith(string) for more than one element", function() {
|
|||||||
equal(jQuery("#foo p").length, 0, "verify that all the three original element have been replaced");
|
equal(jQuery("#foo p").length, 0, "verify that all the three original element have been replaced");
|
||||||
});
|
});
|
||||||
|
|
||||||
test( "Empty replaceWith (#13401; #13596)", 8, function() {
|
test( "Empty replaceWith (trac-13401; trac-13596; gh-2204)", function() {
|
||||||
var $el = jQuery( "<div/>" ),
|
|
||||||
|
expect( 25 );
|
||||||
|
|
||||||
|
var $el = jQuery( "<div/><div/>" ).html( "<p>0</p>" ),
|
||||||
|
expectedHTML = $el.html(),
|
||||||
tests = {
|
tests = {
|
||||||
"empty string": "",
|
"empty string": "",
|
||||||
"empty array": [],
|
"empty array": [],
|
||||||
|
"array of empty string": [ "" ],
|
||||||
"empty collection": jQuery( "#nonexistent" ),
|
"empty collection": jQuery( "#nonexistent" ),
|
||||||
|
|
||||||
// in case of jQuery(...).replaceWith();
|
// in case of jQuery(...).replaceWith();
|
||||||
"empty undefined": undefined
|
"undefined": undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
jQuery.each( tests, function( label, input ) {
|
jQuery.each( tests, function( label, input ) {
|
||||||
@ -1345,6 +1350,17 @@ test( "Empty replaceWith (#13401; #13596)", 8, function() {
|
|||||||
strictEqual( $el.html(), "", "replaceWith(" + label + ")" );
|
strictEqual( $el.html(), "", "replaceWith(" + label + ")" );
|
||||||
$el.html( "<b/>" ).children().replaceWith(function() { return input; });
|
$el.html( "<b/>" ).children().replaceWith(function() { return input; });
|
||||||
strictEqual( $el.html(), "", "replaceWith(function returning " + label + ")" );
|
strictEqual( $el.html(), "", "replaceWith(function returning " + label + ")" );
|
||||||
|
$el.html( "<i/>" ).children().replaceWith(function( i ) { i; return input; });
|
||||||
|
strictEqual( $el.html(), "", "replaceWith(other function returning " + label + ")" );
|
||||||
|
$el.html( "<p/>" ).children().replaceWith(function( i ) {
|
||||||
|
return i ?
|
||||||
|
input :
|
||||||
|
jQuery( this ).html( i + "" );
|
||||||
|
});
|
||||||
|
strictEqual( $el.eq( 0 ).html(), expectedHTML,
|
||||||
|
"replaceWith(function conditionally returning context)" );
|
||||||
|
strictEqual( $el.eq( 1 ).html(), "",
|
||||||
|
"replaceWith(function conditionally returning " + label + ")" );
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user