src/manipulation.js

Maintainability

65.03

Lines of code

486

Created with Raphaël 2.1.002550751002016-7-102016-6-102016-5-112016-4-112016-3-122016-2-112016-1-12

2016-8-9
Maintainability: 65.03

Created with Raphaël 2.1.001252503755002016-7-102016-6-102016-5-112016-4-112016-3-122016-2-112016-1-12

2016-8-9
Lines of Code: 486

Difficulty

71.02

Estimated Errors

3.92

Function weight

By Complexity

Created with Raphaël 2.1.0domManip21

By SLOC

Created with Raphaël 2.1.0<anonymous>463
1
define( [
2
    "./core",
3
    "./var/concat",
4
    "./var/push",
5
    "./core/access",
6
    "./manipulation/var/rcheckableType",
7
    "./manipulation/var/rtagName",
8
    "./manipulation/var/rscriptType",
9
    "./manipulation/wrapMap",
10
    "./manipulation/getAll",
11
    "./manipulation/setGlobalEval",
12
    "./manipulation/buildFragment",
13
    "./manipulation/support",
14
 
15
    "./data/var/dataPriv",
16
    "./data/var/dataUser",
17
    "./data/var/acceptData",
18
    "./core/DOMEval",
19
 
20
    "./core/init",
21
    "./traversing",
22
    "./selector",
23
    "./event"
24
], function( jQuery, concat, push, access,
25
    rcheckableType, rtagName, rscriptType,
26
    wrapMap, getAll, setGlobalEval, buildFragment, support,
27
    dataPriv, dataUser, acceptData, DOMEval ) {
28
 
29
"use strict";
30
 
31
var
32
 
33
    /* eslint-disable max-len */
34
 
35
    // See https://github.com/eslint/eslint/issues/3229
36
    rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
37
 
38
    /* eslint-enable */
39
 
40
    // Support: IE <=10 - 11, Edge 12 - 13
41
    // In IE/Edge using regex groups here causes severe slowdowns.
42
    // See https://connect.microsoft.com/IE/feedback/details/1736512/
43
    rnoInnerhtml = /<script|<style|<link/i,
44
 
45
    // checked="checked" or checked
46
    rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
47
    rscriptTypeMasked = /^true\/(.*)/,
48
    rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
49
 
50
function manipulationTarget( elem, content ) {
51
    if ( jQuery.nodeName( elem, "table" ) &&
52
        jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
53
 
54
        return elem.getElementsByTagName( "tbody" )[ 0 ] || elem;
55
    }
56
 
57
    return elem;
58
}
59
 
60
// Replace/restore the type attribute of script elements for safe DOM manipulation
61
function disableScript( elem ) {
62
    elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
63
    return elem;
64
}
65
function restoreScript( elem ) {
66
    var match = rscriptTypeMasked.exec( elem.type );
67
 
68
    if ( match ) {
69
        elem.type = match[ 1 ];
70
    } else {
71
        elem.removeAttribute( "type" );
72
    }
73
 
74
    return elem;
75
}
76
 
77
function cloneCopyEvent( src, dest ) {
78
    var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
79
 
80
    if ( dest.nodeType !== 1 ) {
81
        return;
82
    }
83
 
84
    // 1. Copy private data: events, handlers, etc.
85
    if ( dataPriv.hasData( src ) ) {
86
        pdataOld = dataPriv.access( src );
87
        pdataCur = dataPriv.set( dest, pdataOld );
88
        events = pdataOld.events;
89
 
90
        if ( events ) {
91
            delete pdataCur.handle;
92
            pdataCur.events = {};
93
 
94
            for ( type in events ) {
95
                for ( i = 0, l = events[ type ].length; i < l; i++ ) {
96
                    jQuery.event.add( dest, type, events[ type ][ i ] );
97
                }
98
            }
99
        }
100
    }
101
 
102
    // 2. Copy user data
103
    if ( dataUser.hasData( src ) ) {
104
        udataOld = dataUser.access( src );
105
        udataCur = jQuery.extend( {}, udataOld );
106
 
107
        dataUser.set( dest, udataCur );
108
    }
109
}
110
 
111
// Fix IE bugs, see support tests
112
function fixInput( src, dest ) {
113
    var nodeName = dest.nodeName.toLowerCase();
114
 
115
    // Fails to persist the checked state of a cloned checkbox or radio button.
116
    if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
117
        dest.checked = src.checked;
118
 
119
    // Fails to return the selected option to the default selected state when cloning options
120
    } else if ( nodeName === "input" || nodeName === "textarea" ) {
121
        dest.defaultValue = src.defaultValue;
122
    }
123
}
124
 
125
function domManip( collection, args, callback, ignored ) {
126
 
127
    // Flatten any nested arrays
128
    args = concat.apply( [], args );
129
 
130
    var fragment, first, scripts, hasScripts, node, doc,
131
        i = 0,
132
        l = collection.length,
133
        iNoClone = l - 1,
134
        value = args[ 0 ],
135
        isFunction = jQuery.isFunction( value );
136
 
137
    // We can't cloneNode fragments that contain checked, in WebKit
138
    if ( isFunction ||
139
            ( l > 1 && typeof value === "string" &&
140
                !support.checkClone && rchecked.test( value ) ) ) {
141
        return collection.each( function( index ) {
142
            var self = collection.eq( index );
143
            if ( isFunction ) {
144
                args[ 0 ] = value.call( this, index, self.html() );
145
            }
146
            domManip( self, args, callback, ignored );
147
        } );
148
    }
149
 
150
    if ( l ) {
151
        fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
152
        first = fragment.firstChild;
153
 
154
        if ( fragment.childNodes.length === 1 ) {
155
            fragment = first;
156
        }
157
 
158
        // Require either new content or an interest in ignored elements to invoke the callback
159
        if ( first || ignored ) {
160
            scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
161
            hasScripts = scripts.length;
162
 
163
            // Use the original fragment for the last item
164
            // instead of the first because it can end up
165
            // being emptied incorrectly in certain situations (#8070).
166
            for ( ; i < l; i++ ) {
167
                node = fragment;
168
 
169
                if ( i !== iNoClone ) {
170
                    node = jQuery.clone( node, true, true );
171
 
172
                    // Keep references to cloned scripts for later restoration
173
                    if ( hasScripts ) {
174
 
175
                        // Support: Android <=4.0 only, PhantomJS 1 only
176
                        // push.apply(_, arraylike) throws on ancient WebKit
177
                        jQuery.merge( scripts, getAll( node, "script" ) );
178
                    }
179
                }
180
 
181
                callback.call( collection[ i ], node, i );
182
            }
183
 
184
            if ( hasScripts ) {
185
                doc = scripts[ scripts.length - 1 ].ownerDocument;
186
 
187
                // Reenable scripts
188
                jQuery.map( scripts, restoreScript );
189
 
190
                // Evaluate executable scripts on first document insertion
191
                for ( i = 0; i < hasScripts; i++ ) {
192
                    node = scripts[ i ];
193
                    if ( rscriptType.test( node.type || "" ) &&
194
                        !dataPriv.access( node, "globalEval" ) &&
195
                        jQuery.contains( doc, node ) ) {
196
 
197
                        if ( node.src ) {
198
 
199
                            // Optional AJAX dependency, but won't run scripts if not present
200
                            if ( jQuery._evalUrl ) {
201
                                jQuery._evalUrl( node.src );
202
                            }
203
                        } else {
204
                            DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
205
                        }
206
                    }
207
                }
208
            }
209
        }
210
    }
211
 
212
    return collection;
213
}
214
 
215
function remove( elem, selector, keepData ) {
216
    var node,
217
        nodes = selector ? jQuery.filter( selector, elem ) : elem,
218
        i = 0;
219
 
220
    for ( ; ( node = nodes[ i ] ) != null; i++ ) {
Column: 35 "Use '!==' to compare with 'null'."
221
        if ( !keepData && node.nodeType === 1 ) {
222
            jQuery.cleanData( getAll( node ) );
223
        }
224
 
225
        if ( node.parentNode ) {
226
            if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
227
                setGlobalEval( getAll( node, "script" ) );
228
            }
229
            node.parentNode.removeChild( node );
230
        }
231
    }
232
 
233
    return elem;
234
}
235
 
236
jQuery.extend( {
237
    htmlPrefilter: function( html ) {
238
        return html.replace( rxhtmlTag, "<$1></$2>" );
239
    },
240
 
241
    clone: function( elem, dataAndEvents, deepDataAndEvents ) {
242
        var i, l, srcElements, destElements,
243
            clone = elem.cloneNode( true ),
244
            inPage = jQuery.contains( elem.ownerDocument, elem );
245
 
246
        // Fix IE cloning issues
247
        if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
248
                !jQuery.isXMLDoc( elem ) ) {
249
 
250
            // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
251
            destElements = getAll( clone );
252
            srcElements = getAll( elem );
253
 
254
            for ( i = 0, l = srcElements.length; i < l; i++ ) {
255
                fixInput( srcElements[ i ], destElements[ i ] );
256
            }
257
        }
258
 
259
        // Copy the events from the original to the clone
260
        if ( dataAndEvents ) {
261
            if ( deepDataAndEvents ) {
262
                srcElements = srcElements || getAll( elem );
263
                destElements = destElements || getAll( clone );
264
 
265
                for ( i = 0, l = srcElements.length; i < l; i++ ) {
266
                    cloneCopyEvent( srcElements[ i ], destElements[ i ] );
267
                }
268
            } else {
269
                cloneCopyEvent( elem, clone );
270
            }
271
        }
272
 
273
        // Preserve script evaluation history
274
        destElements = getAll( clone, "script" );
275
        if ( destElements.length > 0 ) {
276
            setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
277
        }
278
 
279
        // Return the cloned set
280
        return clone;
281
    },
282
 
283
    cleanData: function( elems ) {
284
        var data, elem, type,
285
            special = jQuery.event.special,
286
            i = 0;
287
 
288
        for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
289
            if ( acceptData( elem ) ) {
290
                if ( ( data = elem[ dataPriv.expando ] ) ) {
291
                    if ( data.events ) {
292
                        for ( type in data.events ) {
293
                            if ( special[ type ] ) {
294
                                jQuery.event.remove( elem, type );
295
 
296
                            // This is a shortcut to avoid jQuery.event.remove's overhead
297
                            } else {
298
                                jQuery.removeEvent( elem, type, data.handle );
299
                            }
300
                        }
301
                    }
302
 
303
                    // Support: Chrome <=35 - 45+
304
                    // Assign undefined instead of using delete, see Data#remove
305
                    elem[ dataPriv.expando ] = undefined;
306
                }
307
                if ( elem[ dataUser.expando ] ) {
308
 
309
                    // Support: Chrome <=35 - 45+
310
                    // Assign undefined instead of using delete, see Data#remove
311
                    elem[ dataUser.expando ] = undefined;
312
                }
313
            }
314
        }
315
    }
316
} );
317
 
318
jQuery.fn.extend( {
319
    detach: function( selector ) {
320
        return remove( this, selector, true );
321
    },
322
 
323
    remove: function( selector ) {
324
        return remove( this, selector );
325
    },
326
 
327
    text: function( value ) {
328
        return access( this, function( value ) {
329
            return value === undefined ?
330
                jQuery.text( this ) :
331
                this.empty().each( function() {
332
                    if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
333
                        this.textContent = value;
334
                    }
335
                } );
336
        }, null, value, arguments.length );
337
    },
338
 
339
    append: function() {
340
        return domManip( this, arguments, function( elem ) {
341
            if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
342
                var target = manipulationTarget( this, elem );
343
                target.appendChild( elem );
344
            }
345
        } );
346
    },
347
 
348
    prepend: function() {
349
        return domManip( this, arguments, function( elem ) {
350
            if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
351
                var target = manipulationTarget( this, elem );
352
                target.insertBefore( elem, target.firstChild );
353
            }
354
        } );
355
    },
356
 
357
    before: function() {
358
        return domManip( this, arguments, function( elem ) {
359
            if ( this.parentNode ) {
360
                this.parentNode.insertBefore( elem, this );
361
            }
362
        } );
363
    },
364
 
365
    after: function() {
366
        return domManip( this, arguments, function( elem ) {
367
            if ( this.parentNode ) {
368
                this.parentNode.insertBefore( elem, this.nextSibling );
369
            }
370
        } );
371
    },
372
 
373
    empty: function() {
374
        var elem,
375
            i = 0;
376
 
377
        for ( ; ( elem = this[ i ] ) != null; i++ ) {
Column: 38 "Use '!==' to compare with 'null'."
378
            if ( elem.nodeType === 1 ) {
379
 
380
                // Prevent memory leaks
381
                jQuery.cleanData( getAll( elem, false ) );
382
 
383
                // Remove any remaining nodes
384
                elem.textContent = "";
385
            }
386
        }
387
 
388
        return this;
389
    },
390
 
391
    clone: function( dataAndEvents, deepDataAndEvents ) {
392
        dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
Column: 39 "Use '===' to compare with 'null'."
393
        deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
Column: 47 "Use '===' to compare with 'null'."
394
 
395
        return this.map( function() {
396
            return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
397
        } );
398
    },
399
 
400
    html: function( value ) {
401
        return access( this, function( value ) {
402
            var elem = this[ 0 ] || {},
403
                i = 0,
404
                l = this.length;
405
 
406
            if ( value === undefined && elem.nodeType === 1 ) {
407
                return elem.innerHTML;
408
            }
409
 
410
            // See if we can take a shortcut and just use innerHTML
411
            if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
412
                !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
413
 
414
                value = jQuery.htmlPrefilter( value );
415
 
416
                try {
417
                    for ( ; i < l; i++ ) {
418
                        elem = this[ i ] || {};
419
 
420
                        // Remove element nodes and prevent memory leaks
421
                        if ( elem.nodeType === 1 ) {
422
                            jQuery.cleanData( getAll( elem, false ) );
423
                            elem.innerHTML = value;
424
                        }
425
                    }
426
 
427
                    elem = 0;
428
 
429
                // If using innerHTML throws an exception, use the fallback method
430
                } catch ( e ) {}
431
            }
432
 
433
            if ( elem ) {
434
                this.empty().append( value );
435
            }
436
        }, null, value, arguments.length );
437
    },
438
 
439
    replaceWith: function() {
440
        var ignored = [];
441
 
442
        // Make the changes, replacing each non-ignored context element with the new content
443
        return domManip( this, arguments, function( elem ) {
444
            var parent = this.parentNode;
445
 
446
            if ( jQuery.inArray( this, ignored ) < 0 ) {
447
                jQuery.cleanData( getAll( this ) );
448
                if ( parent ) {
449
                    parent.replaceChild( elem, this );
450
                }
451
            }
452
 
453
        // Force callback invocation
454
        }, ignored );
455
    }
456
} );
457
 
458
jQuery.each( {
459
    appendTo: "append",
460
    prependTo: "prepend",
461
    insertBefore: "before",
462
    insertAfter: "after",
463
    replaceAll: "replaceWith"
464
}, function( name, original ) {
465
    jQuery.fn[ name ] = function( selector ) {
466
        var elems,
467
            ret = [],
468
            insert = jQuery( selector ),
469
            last = insert.length - 1,
470
            i = 0;
471
 
472
        for ( ; i <= last; i++ ) {
473
            elems = i === last ? this : this.clone( true );
474
            jQuery( insert[ i ] )[ original ]( elems );
475
 
476
            // Support: Android <=4.0 only, PhantomJS 1 only
477
            // .get() because push.apply(_, arraylike) throws on ancient WebKit
478
            push.apply( ret, elems.get() );
479
        }
480
 
481
        return this.pushStack( ret );
482
    };
483
} );
484
 
485
return jQuery;
486
} );