Manipulation: privatize internal domManip() function

Fixes gh-2225
This commit is contained in:
Timmy Willison
2015-05-05 11:52:58 -07:00
parent a74320fca8
commit 62d5579578

View File

@@ -108,6 +108,94 @@ function fixInput( src, dest ) {
}
}
function domManip( collection, args, callback, ignored ) {
// Flatten any nested arrays
args = concat.apply( [], args );
var fragment, first, scripts, hasScripts, node, doc,
i = 0,
l = collection.length,
iNoClone = l - 1,
value = args[ 0 ],
isFunction = jQuery.isFunction( value );
// We can't cloneNode fragments that contain checked, in WebKit
if ( isFunction ||
( l > 1 && typeof value === "string" &&
!support.checkClone && rchecked.test( value ) ) ) {
return collection.each(function( index ) {
var self = collection.eq( index );
if ( isFunction ) {
args[ 0 ] = value.call( this, index, self.html() );
}
domManip( self, args, callback, ignored );
});
}
if ( l ) {
fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
first = fragment.firstChild;
if ( fragment.childNodes.length === 1 ) {
fragment = 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 );
hasScripts = scripts.length;
// Use the original fragment for the last item
// instead of the first because it can end up
// being emptied incorrectly in certain situations (#8070).
for ( ; i < l; i++ ) {
node = fragment;
if ( i !== iNoClone ) {
node = jQuery.clone( node, true, true );
// Keep references to cloned scripts for later restoration
if ( hasScripts ) {
// Support: Android<4.1, PhantomJS<2
// push.apply(_, arraylike) throws on ancient WebKit
jQuery.merge( scripts, getAll( node, "script" ) );
}
}
callback.call( collection[ i ], node, i );
}
if ( hasScripts ) {
doc = scripts[ scripts.length - 1 ].ownerDocument;
// Reenable scripts
jQuery.map( scripts, restoreScript );
// Evaluate executable scripts on first document insertion
for ( i = 0; i < hasScripts; i++ ) {
node = scripts[ i ];
if ( rscriptType.test( node.type || "" ) &&
!dataPriv.access( node, "globalEval" ) &&
jQuery.contains( doc, node ) ) {
if ( node.src ) {
// Optional AJAX dependency, but won't run scripts if not present
if ( jQuery._evalUrl ) {
jQuery._evalUrl( node.src );
}
} else {
jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
}
}
}
}
}
}
return collection;
}
jQuery.extend({
htmlPrefilter: function( html ) {
return html.replace( rxhtmlTag, "<$1></$2>" );
@@ -193,7 +281,7 @@ jQuery.fn.extend({
},
append: function() {
return this.domManip( arguments, function( elem ) {
return domManip( this, arguments, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
var target = manipulationTarget( this, elem );
target.appendChild( elem );
@@ -202,7 +290,7 @@ jQuery.fn.extend({
},
prepend: function() {
return this.domManip( arguments, function( elem ) {
return domManip( this, arguments, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
var target = manipulationTarget( this, elem );
target.insertBefore( elem, target.firstChild );
@@ -211,7 +299,7 @@ jQuery.fn.extend({
},
before: function() {
return this.domManip( arguments, function( elem ) {
return domManip( this, arguments, function( elem ) {
if ( this.parentNode ) {
this.parentNode.insertBefore( elem, this );
}
@@ -219,7 +307,7 @@ jQuery.fn.extend({
},
after: function() {
return this.domManip( arguments, function( elem ) {
return domManip( this, arguments, function( elem ) {
if ( this.parentNode ) {
this.parentNode.insertBefore( elem, this.nextSibling );
}
@@ -317,7 +405,7 @@ jQuery.fn.extend({
var ignored = [];
// Make the changes, replacing each non-ignored context element with the new content
return this.domManip( arguments, function( elem ) {
return domManip( this, arguments, function( elem ) {
var parent = this.parentNode;
if ( jQuery.inArray( this, ignored ) < 0 ) {
@@ -333,95 +421,6 @@ jQuery.fn.extend({
detach: function( selector ) {
return this.remove( selector, true );
},
domManip: function( args, callback, ignored ) {
// Flatten any nested arrays
args = concat.apply( [], args );
var fragment, first, scripts, hasScripts, node, doc,
i = 0,
l = this.length,
set = this,
iNoClone = l - 1,
value = args[ 0 ],
isFunction = jQuery.isFunction( value );
// We can't cloneNode fragments that contain checked, in WebKit
if ( isFunction ||
( l > 1 && typeof value === "string" &&
!support.checkClone && rchecked.test( value ) ) ) {
return this.each(function( index ) {
var self = set.eq( index );
if ( isFunction ) {
args[ 0 ] = value.call( this, index, self.html() );
}
self.domManip( args, callback, ignored );
});
}
if ( l ) {
fragment = buildFragment( args, this[ 0 ].ownerDocument, false, this, ignored );
first = fragment.firstChild;
if ( fragment.childNodes.length === 1 ) {
fragment = 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 );
hasScripts = scripts.length;
// Use the original fragment for the last item
// instead of the first because it can end up
// being emptied incorrectly in certain situations (#8070).
for ( ; i < l; i++ ) {
node = fragment;
if ( i !== iNoClone ) {
node = jQuery.clone( node, true, true );
// Keep references to cloned scripts for later restoration
if ( hasScripts ) {
// Support: Android<4.1, PhantomJS<2
// push.apply(_, arraylike) throws on ancient WebKit
jQuery.merge( scripts, getAll( node, "script" ) );
}
}
callback.call( this[ i ], node, i );
}
if ( hasScripts ) {
doc = scripts[ scripts.length - 1 ].ownerDocument;
// Reenable scripts
jQuery.map( scripts, restoreScript );
// Evaluate executable scripts on first document insertion
for ( i = 0; i < hasScripts; i++ ) {
node = scripts[ i ];
if ( rscriptType.test( node.type || "" ) &&
!dataPriv.access( node, "globalEval" ) &&
jQuery.contains( doc, node ) ) {
if ( node.src ) {
// Optional AJAX dependency, but won't run scripts if not present
if ( jQuery._evalUrl ) {
jQuery._evalUrl( node.src );
}
} else {
jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
}
}
}
}
}
}
return this;
}
});