Fix #11291. Always clone XML docs with a genuine .cloneNode().
[jquery.git] / src / manipulation.js
blobb295f4b7e81da07af9abe6d74c3b0cb0e8d95824
1 (function( jQuery ) {
3 function createSafeFragment( document ) {
4         var list = nodeNames.split( "|" ),
5         safeFrag = document.createDocumentFragment();
7         if ( safeFrag.createElement ) {
8                 while ( list.length ) {
9                         safeFrag.createElement(
10                                 list.pop()
11                         );
12                 }
13         }
14         return safeFrag;
17 var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
18                 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
19         rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
20         rleadingWhitespace = /^\s+/,
21         rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
22         rtagName = /<([\w:]+)/,
23         rtbody = /<tbody/i,
24         rhtml = /<|&#?\w+;/,
25         rnoInnerhtml = /<(?:script|style)/i,
26         rnocache = /<(?:script|object|embed|option|style)/i,
27     rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
28         // checked="checked" or checked
29         rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
30         rscriptType = /\/(java|ecma)script/i,
31         rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
32         wrapMap = {
33                 option: [ 1, "<select multiple='multiple'>", "</select>" ],
34                 legend: [ 1, "<fieldset>", "</fieldset>" ],
35                 thead: [ 1, "<table>", "</table>" ],
36                 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
37                 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
38                 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
39                 area: [ 1, "<map>", "</map>" ],
40                 _default: [ 0, "", "" ]
41         },
42         safeFragment = createSafeFragment( document );
44 wrapMap.optgroup = wrapMap.option;
45 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
46 wrapMap.th = wrapMap.td;
48 // IE can't serialize <link> and <script> tags normally
49 if ( !jQuery.support.htmlSerialize ) {
50         wrapMap._default = [ 1, "div<div>", "</div>" ];
53 jQuery.fn.extend({
54         text: function( value ) {
55                 return jQuery.access( this, function( value ) {
56                         return value === undefined ?
57                                 jQuery.text( this ) :
58                                 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
59                 }, null, value, arguments.length );
60         },
62         wrapAll: function( html ) {
63                 if ( jQuery.isFunction( html ) ) {
64                         return this.each(function(i) {
65                                 jQuery(this).wrapAll( html.call(this, i) );
66                         });
67                 }
69                 if ( this[0] ) {
70                         // The elements to wrap the target around
71                         var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
73                         if ( this[0].parentNode ) {
74                                 wrap.insertBefore( this[0] );
75                         }
77                         wrap.map(function() {
78                                 var elem = this;
80                                 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
81                                         elem = elem.firstChild;
82                                 }
84                                 return elem;
85                         }).append( this );
86                 }
88                 return this;
89         },
91         wrapInner: function( html ) {
92                 if ( jQuery.isFunction( html ) ) {
93                         return this.each(function(i) {
94                                 jQuery(this).wrapInner( html.call(this, i) );
95                         });
96                 }
98                 return this.each(function() {
99                         var self = jQuery( this ),
100                                 contents = self.contents();
102                         if ( contents.length ) {
103                                 contents.wrapAll( html );
105                         } else {
106                                 self.append( html );
107                         }
108                 });
109         },
111         wrap: function( html ) {
112                 var isFunction = jQuery.isFunction( html );
114                 return this.each(function(i) {
115                         jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
116                 });
117         },
119         unwrap: function() {
120                 return this.parent().each(function() {
121                         if ( !jQuery.nodeName( this, "body" ) ) {
122                                 jQuery( this ).replaceWith( this.childNodes );
123                         }
124                 }).end();
125         },
127         append: function() {
128                 return this.domManip(arguments, true, function( elem ) {
129                         if ( this.nodeType === 1 ) {
130                                 this.appendChild( elem );
131                         }
132                 });
133         },
135         prepend: function() {
136                 return this.domManip(arguments, true, function( elem ) {
137                         if ( this.nodeType === 1 ) {
138                                 this.insertBefore( elem, this.firstChild );
139                         }
140                 });
141         },
143         before: function() {
144                 if ( this[0] && this[0].parentNode ) {
145                         return this.domManip(arguments, false, function( elem ) {
146                                 this.parentNode.insertBefore( elem, this );
147                         });
148                 } else if ( arguments.length ) {
149                         var set = jQuery.clean( arguments );
150                         set.push.apply( set, this.toArray() );
151                         return this.pushStack( set, "before", arguments );
152                 }
153         },
155         after: function() {
156                 if ( this[0] && this[0].parentNode ) {
157                         return this.domManip(arguments, false, function( elem ) {
158                                 this.parentNode.insertBefore( elem, this.nextSibling );
159                         });
160                 } else if ( arguments.length ) {
161                         var set = this.pushStack( this, "after", arguments );
162                         set.push.apply( set, jQuery.clean(arguments) );
163                         return set;
164                 }
165         },
167         // keepData is for internal use only--do not document
168         remove: function( selector, keepData ) {
169                 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
170                         if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
171                                 if ( !keepData && elem.nodeType === 1 ) {
172                                         jQuery.cleanData( elem.getElementsByTagName("*") );
173                                         jQuery.cleanData( [ elem ] );
174                                 }
176                                 if ( elem.parentNode ) {
177                                         elem.parentNode.removeChild( elem );
178                                 }
179                         }
180                 }
182                 return this;
183         },
185         empty: function() {
186                 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
187                         // Remove element nodes and prevent memory leaks
188                         if ( elem.nodeType === 1 ) {
189                                 jQuery.cleanData( elem.getElementsByTagName("*") );
190                         }
192                         // Remove any remaining nodes
193                         while ( elem.firstChild ) {
194                                 elem.removeChild( elem.firstChild );
195                         }
196                 }
198                 return this;
199         },
201         clone: function( dataAndEvents, deepDataAndEvents ) {
202                 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
203                 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
205                 return this.map( function () {
206                         return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
207                 });
208         },
210         html: function( value ) {
211                 return jQuery.access( this, function( value ) {
212                         var elem = this[0] || {},
213                                 i = 0,
214                                 l = this.length;
216                         if ( value === undefined ) {
217                                 return elem.nodeType === 1 ?
218                                         elem.innerHTML.replace( rinlinejQuery, "" ) :
219                                         null;
220                         }
223                         if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
224                                 ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
225                                 !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
227                                 value = value.replace( rxhtmlTag, "<$1></$2>" );
229                                 try {
230                                         for (; i < l; i++ ) {
231                                                 // Remove element nodes and prevent memory leaks
232                                                 elem = this[i] || {};
233                                                 if ( elem.nodeType === 1 ) {
234                                                         jQuery.cleanData( elem.getElementsByTagName( "*" ) );
235                                                         elem.innerHTML = value;
236                                                 }
237                                         }
239                                         elem = 0;
241                                 // If using innerHTML throws an exception, use the fallback method
242                                 } catch(e) {}
243                         }
245                         if ( elem ) {
246                                 this.empty().append( value );
247                         }
248                 }, null, value, arguments.length );
249         },
251         replaceWith: function( value ) {
252                 if ( this[0] && this[0].parentNode ) {
253                         // Make sure that the elements are removed from the DOM before they are inserted
254                         // this can help fix replacing a parent with child elements
255                         if ( jQuery.isFunction( value ) ) {
256                                 return this.each(function(i) {
257                                         var self = jQuery(this), old = self.html();
258                                         self.replaceWith( value.call( this, i, old ) );
259                                 });
260                         }
262                         if ( typeof value !== "string" ) {
263                                 value = jQuery( value ).detach();
264                         }
266                         return this.each(function() {
267                                 var next = this.nextSibling,
268                                         parent = this.parentNode;
270                                 jQuery( this ).remove();
272                                 if ( next ) {
273                                         jQuery(next).before( value );
274                                 } else {
275                                         jQuery(parent).append( value );
276                                 }
277                         });
278                 } else {
279                         return this.length ?
280                                 this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
281                                 this;
282                 }
283         },
285         detach: function( selector ) {
286                 return this.remove( selector, true );
287         },
289         domManip: function( args, table, callback ) {
290                 var results, first, fragment, parent,
291                         value = args[0],
292                         scripts = [];
294                 // We can't cloneNode fragments that contain checked, in WebKit
295                 if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
296                         return this.each(function() {
297                                 jQuery(this).domManip( args, table, callback, true );
298                         });
299                 }
301                 if ( jQuery.isFunction(value) ) {
302                         return this.each(function(i) {
303                                 var self = jQuery(this);
304                                 args[0] = value.call(this, i, table ? self.html() : undefined);
305                                 self.domManip( args, table, callback );
306                         });
307                 }
309                 if ( this[0] ) {
310                         parent = value && value.parentNode;
312                         // If we're in a fragment, just use that instead of building a new one
313                         if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
314                                 results = { fragment: parent };
316                         } else {
317                                 results = jQuery.buildFragment( args, this, scripts );
318                         }
320                         fragment = results.fragment;
322                         if ( fragment.childNodes.length === 1 ) {
323                                 first = fragment = fragment.firstChild;
324                         } else {
325                                 first = fragment.firstChild;
326                         }
328                         if ( first ) {
329                                 table = table && jQuery.nodeName( first, "tr" );
331                                 for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
332                                         callback.call(
333                                                 table ?
334                                                         root(this[i], first) :
335                                                         this[i],
336                                                 // Make sure that we do not leak memory by inadvertently discarding
337                                                 // the original fragment (which might have attached data) instead of
338                                                 // using it; in addition, use the original fragment object for the last
339                                                 // item instead of first because it can end up being emptied incorrectly
340                                                 // in certain situations (Bug #8070).
341                                                 // Fragments from the fragment cache must always be cloned and never used
342                                                 // in place.
343                                                 results.cacheable || ( l > 1 && i < lastIndex ) ?
344                                                         jQuery.clone( fragment, true, true ) :
345                                                         fragment
346                                         );
347                                 }
348                         }
350                         if ( scripts.length ) {
351                                 jQuery.each( scripts, function( i, elem ) {
352                                         if ( elem.src ) {
353                                                 jQuery.ajax({
354                                                         url: elem.src,
355                                                         async: false,
356                                                         dataType: "script"
357                                                 });
358                                         } else {
359                                                 jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
360                                         }
362                                         if ( elem.parentNode ) {
363                                                 elem.parentNode.removeChild( elem );
364                                         }
365                                 });
366                         }
367                 }
369                 return this;
370         }
373 function root( elem, cur ) {
374         return jQuery.nodeName(elem, "table") ?
375                 (elem.getElementsByTagName("tbody")[0] ||
376                 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
377                 elem;
380 function cloneCopyEvent( src, dest ) {
382         if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
383                 return;
384         }
386         var type, i, l,
387                 oldData = jQuery._data( src ),
388                 curData = jQuery._data( dest, oldData ),
389                 events = oldData.events;
391         if ( events ) {
392                 delete curData.handle;
393                 curData.events = {};
395                 for ( type in events ) {
396                         for ( i = 0, l = events[ type ].length; i < l; i++ ) {
397                                 jQuery.event.add( dest, type, events[ type ][ i ] );
398                         }
399                 }
400         }
402         // make the cloned public data object a copy from the original
403         if ( curData.data ) {
404                 curData.data = jQuery.extend( {}, curData.data );
405         }
408 function cloneFixAttributes( src, dest ) {
409         var nodeName;
411         // We do not need to do anything for non-Elements
412         if ( dest.nodeType !== 1 ) {
413                 return;
414         }
416         // clearAttributes removes the attributes, which we don't want,
417         // but also removes the attachEvent events, which we *do* want
418         if ( dest.clearAttributes ) {
419                 dest.clearAttributes();
420         }
422         // mergeAttributes, in contrast, only merges back on the
423         // original attributes, not the events
424         if ( dest.mergeAttributes ) {
425                 dest.mergeAttributes( src );
426         }
428         nodeName = dest.nodeName.toLowerCase();
430         // IE6-8 fail to clone children inside object elements that use
431         // the proprietary classid attribute value (rather than the type
432         // attribute) to identify the type of content to display
433         if ( nodeName === "object" ) {
434                 dest.outerHTML = src.outerHTML;
436         } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
437                 // IE6-8 fails to persist the checked state of a cloned checkbox
438                 // or radio button. Worse, IE6-7 fail to give the cloned element
439                 // a checked appearance if the defaultChecked value isn't also set
440                 if ( src.checked ) {
441                         dest.defaultChecked = dest.checked = src.checked;
442                 }
444                 // IE6-7 get confused and end up setting the value of a cloned
445                 // checkbox/radio button to an empty string instead of "on"
446                 if ( dest.value !== src.value ) {
447                         dest.value = src.value;
448                 }
450         // IE6-8 fails to return the selected option to the default selected
451         // state when cloning options
452         } else if ( nodeName === "option" ) {
453                 dest.selected = src.defaultSelected;
455         // IE6-8 fails to set the defaultValue to the correct value when
456         // cloning other types of input fields
457         } else if ( nodeName === "input" || nodeName === "textarea" ) {
458                 dest.defaultValue = src.defaultValue;
459         }
461         // Event data gets referenced instead of copied if the expando
462         // gets copied too
463         dest.removeAttribute( jQuery.expando );
465         // Clear flags for bubbling special change/submit events, they must
466         // be reattached when the newly cloned events are first activated
467         dest.removeAttribute( "_submit_attached" );
468         dest.removeAttribute( "_change_attached" );
471 jQuery.buildFragment = function( args, nodes, scripts ) {
472         var fragment, cacheable, cacheresults, doc,
473         first = args[ 0 ];
475         // nodes may contain either an explicit document object,
476         // a jQuery collection or context object.
477         // If nodes[0] contains a valid object to assign to doc
478         if ( nodes && nodes[0] ) {
479                 doc = nodes[0].ownerDocument || nodes[0];
480         }
482         // Ensure that an attr object doesn't incorrectly stand in as a document object
483         // Chrome and Firefox seem to allow this to occur and will throw exception
484         // Fixes #8950
485         if ( !doc.createDocumentFragment ) {
486                 doc = document;
487         }
489         // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
490         // Cloning options loses the selected state, so don't cache them
491         // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
492         // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
493         // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
494         if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
495                 first.charAt(0) === "<" && !rnocache.test( first ) &&
496                 (jQuery.support.checkClone || !rchecked.test( first )) &&
497                 (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
499                 cacheable = true;
501                 cacheresults = jQuery.fragments[ first ];
502                 if ( cacheresults && cacheresults !== 1 ) {
503                         fragment = cacheresults;
504                 }
505         }
507         if ( !fragment ) {
508                 fragment = doc.createDocumentFragment();
509                 jQuery.clean( args, doc, fragment, scripts );
510         }
512         if ( cacheable ) {
513                 jQuery.fragments[ first ] = cacheresults ? fragment : 1;
514         }
516         return { fragment: fragment, cacheable: cacheable };
519 jQuery.fragments = {};
521 jQuery.each({
522         appendTo: "append",
523         prependTo: "prepend",
524         insertBefore: "before",
525         insertAfter: "after",
526         replaceAll: "replaceWith"
527 }, function( name, original ) {
528         jQuery.fn[ name ] = function( selector ) {
529                 var ret = [],
530                         insert = jQuery( selector ),
531                         parent = this.length === 1 && this[0].parentNode;
533                 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
534                         insert[ original ]( this[0] );
535                         return this;
537                 } else {
538                         for ( var i = 0, l = insert.length; i < l; i++ ) {
539                                 var elems = ( i > 0 ? this.clone(true) : this ).get();
540                                 jQuery( insert[i] )[ original ]( elems );
541                                 ret = ret.concat( elems );
542                         }
544                         return this.pushStack( ret, name, insert.selector );
545                 }
546         };
549 function getAll( elem ) {
550         if ( typeof elem.getElementsByTagName !== "undefined" ) {
551                 return elem.getElementsByTagName( "*" );
553         } else if ( typeof elem.querySelectorAll !== "undefined" ) {
554                 return elem.querySelectorAll( "*" );
556         } else {
557                 return [];
558         }
561 // Used in clean, fixes the defaultChecked property
562 function fixDefaultChecked( elem ) {
563         if ( elem.type === "checkbox" || elem.type === "radio" ) {
564                 elem.defaultChecked = elem.checked;
565         }
567 // Finds all inputs and passes them to fixDefaultChecked
568 function findInputs( elem ) {
569         var nodeName = ( elem.nodeName || "" ).toLowerCase();
570         if ( nodeName === "input" ) {
571                 fixDefaultChecked( elem );
572         // Skip scripts, get other children
573         } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
574                 jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
575         }
578 // Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
579 function shimCloneNode( elem ) {
580         var div = document.createElement( "div" );
581         safeFragment.appendChild( div );
583         div.innerHTML = elem.outerHTML;
584         return div.firstChild;
587 jQuery.extend({
588         clone: function( elem, dataAndEvents, deepDataAndEvents ) {
589                 var srcElements,
590                         destElements,
591                         i,
592                         // IE<=8 does not properly clone detached, unknown element nodes
593                         clone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ?
594                                 elem.cloneNode( true ) :
595                                 shimCloneNode( elem );
597                 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
598                                 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
599                         // IE copies events bound via attachEvent when using cloneNode.
600                         // Calling detachEvent on the clone will also remove the events
601                         // from the original. In order to get around this, we use some
602                         // proprietary methods to clear the events. Thanks to MooTools
603                         // guys for this hotness.
605                         cloneFixAttributes( elem, clone );
607                         // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
608                         srcElements = getAll( elem );
609                         destElements = getAll( clone );
611                         // Weird iteration because IE will replace the length property
612                         // with an element if you are cloning the body and one of the
613                         // elements on the page has a name or id of "length"
614                         for ( i = 0; srcElements[i]; ++i ) {
615                                 // Ensure that the destination node is not null; Fixes #9587
616                                 if ( destElements[i] ) {
617                                         cloneFixAttributes( srcElements[i], destElements[i] );
618                                 }
619                         }
620                 }
622                 // Copy the events from the original to the clone
623                 if ( dataAndEvents ) {
624                         cloneCopyEvent( elem, clone );
626                         if ( deepDataAndEvents ) {
627                                 srcElements = getAll( elem );
628                                 destElements = getAll( clone );
630                                 for ( i = 0; srcElements[i]; ++i ) {
631                                         cloneCopyEvent( srcElements[i], destElements[i] );
632                                 }
633                         }
634                 }
636                 srcElements = destElements = null;
638                 // Return the cloned set
639                 return clone;
640         },
642         clean: function( elems, context, fragment, scripts ) {
643                 var checkScriptType;
645                 context = context || document;
647                 // !context.createElement fails in IE with an error but returns typeof 'object'
648                 if ( typeof context.createElement === "undefined" ) {
649                         context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
650                 }
652                 var ret = [], j;
654                 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
655                         if ( typeof elem === "number" ) {
656                                 elem += "";
657                         }
659                         if ( !elem ) {
660                                 continue;
661                         }
663                         // Convert html string into DOM nodes
664                         if ( typeof elem === "string" ) {
665                                 if ( !rhtml.test( elem ) ) {
666                                         elem = context.createTextNode( elem );
667                                 } else {
668                                         // Fix "XHTML"-style tags in all browsers
669                                         elem = elem.replace(rxhtmlTag, "<$1></$2>");
671                                         // Trim whitespace, otherwise indexOf won't work as expected
672                                         var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
673                                                 wrap = wrapMap[ tag ] || wrapMap._default,
674                                                 depth = wrap[0],
675                                                 div = context.createElement("div");
677                                         // Append wrapper element to unknown element safe doc fragment
678                                         if ( context === document ) {
679                                                 // Use the fragment we've already created for this document
680                                                 safeFragment.appendChild( div );
681                                         } else {
682                                                 // Use a fragment created with the owner document
683                                                 createSafeFragment( context ).appendChild( div );
684                                         }
686                                         // Go to html and back, then peel off extra wrappers
687                                         div.innerHTML = wrap[1] + elem + wrap[2];
689                                         // Move to the right depth
690                                         while ( depth-- ) {
691                                                 div = div.lastChild;
692                                         }
694                                         // Remove IE's autoinserted <tbody> from table fragments
695                                         if ( !jQuery.support.tbody ) {
697                                                 // String was a <table>, *may* have spurious <tbody>
698                                                 var hasBody = rtbody.test(elem),
699                                                         tbody = tag === "table" && !hasBody ?
700                                                                 div.firstChild && div.firstChild.childNodes :
702                                                                 // String was a bare <thead> or <tfoot>
703                                                                 wrap[1] === "<table>" && !hasBody ?
704                                                                         div.childNodes :
705                                                                         [];
707                                                 for ( j = tbody.length - 1; j >= 0 ; --j ) {
708                                                         if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
709                                                                 tbody[ j ].parentNode.removeChild( tbody[ j ] );
710                                                         }
711                                                 }
712                                         }
714                                         // IE completely kills leading whitespace when innerHTML is used
715                                         if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
716                                                 div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
717                                         }
719                                         elem = div.childNodes;
720                                 }
721                         }
723                         // Resets defaultChecked for any radios and checkboxes
724                         // about to be appended to the DOM in IE 6/7 (#8060)
725                         var len;
726                         if ( !jQuery.support.appendChecked ) {
727                                 if ( elem[0] && typeof (len = elem.length) === "number" ) {
728                                         for ( j = 0; j < len; j++ ) {
729                                                 findInputs( elem[j] );
730                                         }
731                                 } else {
732                                         findInputs( elem );
733                                 }
734                         }
736                         if ( elem.nodeType ) {
737                                 ret.push( elem );
738                         } else {
739                                 ret = jQuery.merge( ret, elem );
740                         }
741                 }
743                 if ( fragment ) {
744                         checkScriptType = function( elem ) {
745                                 return !elem.type || rscriptType.test( elem.type );
746                         };
747                         for ( i = 0; ret[i]; i++ ) {
748                                 if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
749                                         scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
751                                 } else {
752                                         if ( ret[i].nodeType === 1 ) {
753                                                 var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
755                                                 ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
756                                         }
757                                         fragment.appendChild( ret[i] );
758                                 }
759                         }
760                 }
762                 return ret;
763         },
765         cleanData: function( elems ) {
766                 var data, id,
767                         cache = jQuery.cache,
768                         special = jQuery.event.special,
769                         deleteExpando = jQuery.support.deleteExpando;
771                 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
772                         if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
773                                 continue;
774                         }
776                         id = elem[ jQuery.expando ];
778                         if ( id ) {
779                                 data = cache[ id ];
781                                 if ( data && data.events ) {
782                                         for ( var type in data.events ) {
783                                                 if ( special[ type ] ) {
784                                                         jQuery.event.remove( elem, type );
786                                                 // This is a shortcut to avoid jQuery.event.remove's overhead
787                                                 } else {
788                                                         jQuery.removeEvent( elem, type, data.handle );
789                                                 }
790                                         }
792                                         // Null the DOM reference to avoid IE6/7/8 leak (#7054)
793                                         if ( data.handle ) {
794                                                 data.handle.elem = null;
795                                         }
796                                 }
798                                 if ( deleteExpando ) {
799                                         delete elem[ jQuery.expando ];
801                                 } else if ( elem.removeAttribute ) {
802                                         elem.removeAttribute( jQuery.expando );
803                                 }
805                                 delete cache[ id ];
806                         }
807                 }
808         }
811 })( jQuery );