diff options
author | Michał Gołębiowski-Owczarek <m.goleb@gmail.com> | 2022-10-10 18:15:34 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-10 18:15:34 +0200 |
commit | ee6e874075ba1fcd8f9e62cd1ee5c04f6518b6d6 (patch) | |
tree | da232f737c7d41c2c200088fddc3284427bc6ed7 /src/manipulation/domManip.js | |
parent | aa231cd21421503d319ad6068e7df0fb3baa7fea (diff) | |
download | jquery-ee6e874075ba1fcd8f9e62cd1ee5c04f6518b6d6.tar.gz jquery-ee6e874075ba1fcd8f9e62cd1ee5c04f6518b6d6.zip |
Manipulation: Extract domManip to a separate file
We've already had `buildFragment` extracted to a separate file long ago.
`domManip` is quite a complex & crucial API and so far it has existed within
the `manipulation.js` module. Extracting it makes the module shorter and easier
to understand.
A few comments / messages in tests have also been updated to not suggest there's
a public `jQuery.domManip` API - it's been private since 3.0.0.
Closes gh-5138
Diffstat (limited to 'src/manipulation/domManip.js')
-rw-r--r-- | src/manipulation/domManip.js | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/manipulation/domManip.js b/src/manipulation/domManip.js new file mode 100644 index 000000000..f8dded566 --- /dev/null +++ b/src/manipulation/domManip.js @@ -0,0 +1,109 @@ +import jQuery from "../core.js"; +import flat from "../var/flat.js"; +import rscriptType from "./var/rscriptType.js"; +import getAll from "./getAll.js"; +import buildFragment from "./buildFragment.js"; +import dataPriv from "../data/var/dataPriv.js"; +import DOMEval from "../core/DOMEval.js"; + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = typeof value === "function"; + + if ( valueIsFunction ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + 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 (trac-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 ) { + 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 && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce, + crossOrigin: node.crossOrigin + }, doc ); + } + } else { + DOMEval( node.textContent, node, doc ); + } + } + } + } + } + } + + return collection; +} + +export default domManip; |