Manipulation: Extract domManip to a separate file
[jquery.git] / src / manipulation / domManip.js
blobf8dded5663a0a468644e616bfcfe123b3c969b82
1 import jQuery from "../core.js";
2 import flat from "../var/flat.js";
3 import rscriptType from "./var/rscriptType.js";
4 import getAll from "./getAll.js";
5 import buildFragment from "./buildFragment.js";
6 import dataPriv from "../data/var/dataPriv.js";
7 import DOMEval from "../core/DOMEval.js";
9 // Replace/restore the type attribute of script elements for safe DOM manipulation
10 function disableScript( elem ) {
11         elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
12         return elem;
14 function restoreScript( elem ) {
15         if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
16                 elem.type = elem.type.slice( 5 );
17         } else {
18                 elem.removeAttribute( "type" );
19         }
21         return elem;
24 function domManip( collection, args, callback, ignored ) {
26         // Flatten any nested arrays
27         args = flat( args );
29         var fragment, first, scripts, hasScripts, node, doc,
30                 i = 0,
31                 l = collection.length,
32                 iNoClone = l - 1,
33                 value = args[ 0 ],
34                 valueIsFunction = typeof value === "function";
36         if ( valueIsFunction ) {
37                 return collection.each( function( index ) {
38                         var self = collection.eq( index );
39                         args[ 0 ] = value.call( this, index, self.html() );
40                         domManip( self, args, callback, ignored );
41                 } );
42         }
44         if ( l ) {
45                 fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
46                 first = fragment.firstChild;
48                 if ( fragment.childNodes.length === 1 ) {
49                         fragment = first;
50                 }
52                 // Require either new content or an interest in ignored elements to invoke the callback
53                 if ( first || ignored ) {
54                         scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
55                         hasScripts = scripts.length;
57                         // Use the original fragment for the last item
58                         // instead of the first because it can end up
59                         // being emptied incorrectly in certain situations (trac-8070).
60                         for ( ; i < l; i++ ) {
61                                 node = fragment;
63                                 if ( i !== iNoClone ) {
64                                         node = jQuery.clone( node, true, true );
66                                         // Keep references to cloned scripts for later restoration
67                                         if ( hasScripts ) {
68                                                 jQuery.merge( scripts, getAll( node, "script" ) );
69                                         }
70                                 }
72                                 callback.call( collection[ i ], node, i );
73                         }
75                         if ( hasScripts ) {
76                                 doc = scripts[ scripts.length - 1 ].ownerDocument;
78                                 // Reenable scripts
79                                 jQuery.map( scripts, restoreScript );
81                                 // Evaluate executable scripts on first document insertion
82                                 for ( i = 0; i < hasScripts; i++ ) {
83                                         node = scripts[ i ];
84                                         if ( rscriptType.test( node.type || "" ) &&
85                                                 !dataPriv.access( node, "globalEval" ) &&
86                                                 jQuery.contains( doc, node ) ) {
88                                                 if ( node.src && ( node.type || "" ).toLowerCase()  !== "module" ) {
90                                                         // Optional AJAX dependency, but won't run scripts if not present
91                                                         if ( jQuery._evalUrl && !node.noModule ) {
92                                                                 jQuery._evalUrl( node.src, {
93                                                                         nonce: node.nonce,
94                                                                         crossOrigin: node.crossOrigin
95                                                                 }, doc );
96                                                         }
97                                                 } else {
98                                                         DOMEval( node.textContent, node, doc );
99                                                 }
100                                         }
101                                 }
102                         }
103                 }
104         }
106         return collection;
109 export default domManip;