aboutsummaryrefslogtreecommitdiffstats
path: root/src/manipulation/domManip.js
diff options
context:
space:
mode:
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>2022-10-10 18:15:34 +0200
committerGitHub <noreply@github.com>2022-10-10 18:15:34 +0200
commitee6e874075ba1fcd8f9e62cd1ee5c04f6518b6d6 (patch)
treeda232f737c7d41c2c200088fddc3284427bc6ed7 /src/manipulation/domManip.js
parentaa231cd21421503d319ad6068e7df0fb3baa7fea (diff)
downloadjquery-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.js109
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;