diff --git a/src/manipulation.js b/src/manipulation.js index 5fec948cb..9aea16f9d 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -1,25 +1,5 @@ -function createSafeFragment( document ) { - var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); - - if ( safeFrag.createElement ) { - while ( list.length ) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; -} - -var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, - rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, +var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, rtagName = /<([\w:]+)/, - rtbody = /" ], - legend: [ 1, "
" ], - area: [ 1, "" ], - param: [ 1, "" ], - thead: [ 1, "" ], - tr: [ 2, "
" ], - col: [ 2, "
", "
" ], + + tr: [ 1, "" ], td: [ 3, "
" ], + _default: [ 0, "" ] + }; - // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, - // unless wrapped in a div with non-breaking characters in front of it. - _default: jQuery.support.htmlSerialize ? [ 0, "" ] : [ 1, "X
" ] - }, - safeFragment = createSafeFragment( document ), - fragmentDiv = safeFragment.appendChild( document.createElement("div") ); - +// Support: IE 9 wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead = wrapMap.col = wrapMap.tr; wrapMap.th = wrapMap.td; jQuery.fn.extend({ @@ -89,8 +64,8 @@ jQuery.fn.extend({ wrapInner: function( html ) { if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapInner( html.call(this, i) ); + return this.each(function( i ) { + jQuery( this ).wrapInner( html.call(this, i) ); }); } @@ -110,7 +85,7 @@ jQuery.fn.extend({ wrap: function( html ) { var isFunction = jQuery.isFunction( html ); - return this.each(function(i) { + return this.each(function( i ) { jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); }); }, @@ -140,7 +115,7 @@ jQuery.fn.extend({ }, before: function() { - return this.domManip( arguments, false, function( elem ) { + return this.domManip(arguments, false, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this ); } @@ -148,7 +123,7 @@ jQuery.fn.extend({ }, after: function() { - return this.domManip( arguments, false, function( elem ) { + return this.domManip(arguments, false, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this.nextSibling ); } @@ -158,9 +133,12 @@ jQuery.fn.extend({ // keepData is for internal use only--do not document remove: function( selector, keepData ) { var elem, - i = 0; + i = 0, + l = this.length; + + for ( ; i < l; i++ ) { + elem = this[ i ]; - for ( ; (elem = this[i]) != null; i++ ) { if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) { if ( !keepData && elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem ) ); @@ -180,17 +158,19 @@ jQuery.fn.extend({ empty: function() { var elem, - i = 0; + i = 0, + l = this.length; + + for ( ; i < l; i++ ) { + elem = this[ i ]; - for ( ; (elem = this[i]) != null; i++ ) { - // Remove element nodes and prevent memory leaks if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - } - // Remove any remaining nodes - while ( elem.firstChild ) { - elem.removeChild( elem.firstChild ); + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; } } @@ -212,24 +192,21 @@ jQuery.fn.extend({ i = 0, l = this.length; - if ( value === undefined ) { - return elem.nodeType === 1 ? - elem.innerHTML.replace( rinlinejQuery, "" ) : - undefined; + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; } // See if we can take a shortcut and just use innerHTML if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && - ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && - !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { value = value.replace( rxhtmlTag, "<$1>" ); try { - for (; i < l; i++ ) { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + // Remove element nodes and prevent memory leaks - elem = this[i] || {}; if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); elem.innerHTML = value; @@ -239,7 +216,7 @@ jQuery.fn.extend({ elem = 0; // If using innerHTML throws an exception, use the fallback method - } catch(e) {} + } catch( e ) {} } if ( elem ) { @@ -249,11 +226,11 @@ jQuery.fn.extend({ }, replaceWith: function( value ) { - var isFunc = jQuery.isFunction( value ); + var isFunction = jQuery.isFunction( value ); // Make sure that the elements are removed from the DOM before they are inserted // this can help fix replacing a parent with child elements - if ( !isFunc && typeof value !== "string" ) { + if ( !isFunction && typeof value !== "string" ) { value = jQuery( value ).not( this ).detach(); } @@ -296,14 +273,14 @@ jQuery.fn.extend({ return this.each(function( index ) { var self = set.eq( index ); if ( isFunction ) { - args[0] = value.call( this, index, table ? self.html() : undefined ); + args[ 0 ] = value.call( this, index, table ? self.html() : undefined ); } self.domManip( args, table, callback ); }); } - if ( this[0] ) { - doc = this[0].ownerDocument; + if ( l ) { + doc = this[ 0 ].ownerDocument; fragment = doc.createDocumentFragment(); jQuery.clean( args, doc, fragment, undefined, this ); first = fragment.firstChild; @@ -327,14 +304,14 @@ jQuery.fn.extend({ // Keep references to cloned scripts for later restoration if ( hasScripts ) { - jQuery.merge( scripts, getAll( node, "script" ) ); + core_push.apply( scripts, getAll( node, "script" ) ); } } callback.call( - table && jQuery.nodeName( this[i], "table" ) ? - findOrAppend( this[i], "tbody" ) : - this[i], + table && jQuery.nodeName( this[ i ], "table" ) ? + findOrAppend( this[ i ], "tbody" ) : + this[ i ], node, i ); @@ -363,14 +340,11 @@ jQuery.fn.extend({ "throws": true }); } else { - jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); } } } } - - // Fix #11809: Avoid leaking memory - fragment = first = null; } } @@ -378,8 +352,207 @@ jQuery.fn.extend({ } }); +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + core_push.apply( ret, elems ); + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Support: IE >=9 + // Fix Cloning issues + if ( !jQuery.support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + clean: function( elems, context, fragment, scripts, selection ) { + var elem, tmp, tag, wrap, j, ll, + i = 0, + l = elems.length, + ret = [], + container = context === document && fragment; + + // Ensure that context is a document + if ( !context || typeof context.createDocumentFragment === "undefined" ) { + context = document; + } + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + core_push.apply( ret, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + ret.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + + // Ensure a safe container + container = container || context.createDocumentFragment(); + tmp = tmp || container.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1>" ); + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + core_push.apply( ret, tmp.childNodes ); + + // Fix #12392 - remove childNodes parent + tmp.textContent = ""; + + // Remember the top-level container for proper cleanup + tmp = container.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + container.removeChild( tmp ); + } + + if ( fragment ) { + for ( i = 0, l = ret.length; i < l; i++ ) { + elem = ret[ i ]; + container = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + // #4087 - If origin and destination elements are the same, and this is + // that element, do not append to fragment + if ( !selection || jQuery.inArray( elem, selection ) === -1 ) { + fragment.appendChild( elem ); + } + tmp = getAll( elem, "script" ); + + // Preserve script evaluation history + if ( container ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + for ( j = 0, ll = tmp.length; j < ll; j++ ) { + elem = tmp[ j ]; + + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + } + + return ret; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var id, data, elem, type, + l = elems.length, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + special = jQuery.event.special; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + delete cache[ id ]; + delete elem[ internalKey ]; + } + } + } + } + } +}); + function findOrAppend( elem, tag ) { - return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); + return elem.getElementsByTagName( tag )[ 0 ] || elem.appendChild( elem.ownerDocument.createElement(tag) ); } // Replace/restore the type attribute of script elements for safe DOM manipulation @@ -390,20 +563,24 @@ function disableScript( elem ) { } function restoreScript( elem ) { var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { - elem.type = match[1]; + elem.type = match[ 1 ]; + } else { elem.removeAttribute("type"); } + return elem; } // Mark scripts as having already been evaluated function setGlobalEval( elems, refElements ) { - var elem, + var l = elems.length, i = 0; - for ( ; (elem = elems[i]) != null; i++ ) { - jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + + for ( ; i < l; i++ ) { + jQuery._data( elems[ i ], "globalEval", !refElements || jQuery._data( refElements[ i ], "globalEval" ) ); } } @@ -413,7 +590,7 @@ function cloneCopyEvent( src, dest ) { return; } - var type, i, l, + var i, l, type, oldData = jQuery._data( src ), curData = jQuery._data( dest, oldData ), events = oldData.events; @@ -435,356 +612,26 @@ function cloneCopyEvent( src, dest ) { } } -function fixCloneNodeIssues( src, dest ) { - var nodeName, data, e; +function getAll( context, tag ) { + var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : + context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : + []; - // We do not need to do anything for non-Elements - if ( dest.nodeType !== 1 ) { - return; - } + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], ret ) : + ret; +} - nodeName = dest.nodeName.toLowerCase(); +// Support: IE >= 9 +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); - // IE6-8 copies events bound via attachEvent when using cloneNode. - if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { - data = jQuery._data( dest ); + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + dest.checked = src.checked; - for ( e in data.events ) { - jQuery.removeEvent( dest, e, data.handle ); - } - - // Event data gets referenced instead of copied if the expando gets copied too - dest.removeAttribute( jQuery.expando ); - } - - // IE blanks contents when cloning scripts, and tries to evaluate newly-set text - if ( nodeName === "script" && dest.text !== src.text ) { - disableScript( dest ).text = src.text; - restoreScript( dest ); - - // IE6-10 improperly clones children of object elements using classid. - // IE10 throws NoModificationAllowedError if parent is null, #12132. - } else if ( nodeName === "object" ) { - if ( dest.parentNode ) { - dest.outerHTML = src.outerHTML; - } - - // This path appears unavoidable for IE9. When cloning an object - // element in IE9, the outerHTML strategy above is not sufficient. - // If the src has innerHTML and the destination does not, - // copy the src.innerHTML into the dest.innerHTML. #10324 - if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { - dest.innerHTML = src.innerHTML; - } - - } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { - // IE6-8 fails to persist the checked state of a cloned checkbox - // or radio button. Worse, IE6-7 fail to give the cloned element - // a checked appearance if the defaultChecked value isn't also set - - dest.defaultChecked = dest.checked = src.checked; - - // IE6-7 get confused and end up setting the value of a cloned - // checkbox/radio button to an empty string instead of "on" - if ( dest.value !== src.value ) { - dest.value = src.value; - } - - // IE6-8 fails to return the selected option to the default selected - // state when cloning options - } else if ( nodeName === "option" ) { - dest.defaultSelected = dest.selected = src.defaultSelected; - - // IE6-8 fails to set the defaultValue to the correct value when - // cloning other types of input fields + // Fails to return the selected option to the default selected state when cloning options } else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; } } - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - i = 0, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone(true); - jQuery( insert[i] )[ original ]( elems ); - - // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() - core_push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -}); - -function getAll( context, tag ) { - var elems, elem, - i = 0, - found = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( tag || "*" ) : - typeof context.querySelectorAll !== "undefined" ? context.querySelectorAll( tag || "*" ) : - undefined; - - if ( !found ) { - for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { - if ( !tag || jQuery.nodeName( elem, tag ) ) { - found.push( elem ); - } else { - jQuery.merge( found, getAll( elem, tag ) ); - } - } - } - - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], found ) : - found; -} - -// Used in clean, fixes the defaultChecked property -function fixDefaultChecked( elem ) { - if ( manipulation_rcheckableType.test( elem.type ) ) { - elem.defaultChecked = elem.checked; - } -} - -jQuery.extend({ - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var destElements, srcElements, node, i, clone, - inPage = jQuery.contains( elem.ownerDocument, elem ); - - if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { - clone = elem.cloneNode( true ); - - // IE<=8 does not properly clone detached, unknown element nodes - } else { - fragmentDiv.innerHTML = elem.outerHTML; - fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); - } - - if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && - (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - // Fix all IE cloning issues - for ( i = 0; (node = srcElements[i]) != null; ++i ) { - // Ensure that the destination node is not null; Fixes #9587 - if ( destElements[i] ) { - fixCloneNodeIssues( node, destElements[i] ); - } - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0; (node = srcElements[i]) != null; i++ ) { - cloneCopyEvent( node, destElements[i] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - destElements = srcElements = node = null; - - // Return the cloned set - return clone; - }, - - clean: function( elems, context, fragment, scripts, selection ) { - var elem, i, j, tmp, tag, wrap, tbody, - ret = [], - safe = context === document && safeFragment; - - // Ensure that context is a document - if ( !context || typeof context.createDocumentFragment === "undefined" ) { - context = document; - } - - for ( i = 0; (elem = elems[i]) != null; i++ ) { - if ( elem || elem === 0 ) { - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { - jQuery.merge( ret, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - ret.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - // Ensure a safe container - safe = safe || createSafeFragment( context ); - tmp = tmp || safe.appendChild( context.createElement("div") ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + ( wrap[2] || "" ); - - // Descend through wrappers to the right content - j = wrap[0]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Manually add leading whitespace removed by IE - if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { - ret.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); - } - - // Remove IE's autoinserted
from table fragments - if ( !jQuery.support.tbody ) { - - // String was a
, *may* have spurious - elem = tag === "table" && !rtbody.test( elem ) ? - tmp.firstChild : - - // String was a bare or - wrap[1] === "
" && !rtbody.test( elem ) ? - tmp : - 0; - - j = elem && elem.childNodes.length; - while ( j-- ) { - if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { - elem.removeChild( tbody ); - } - } - } - - jQuery.merge( ret, tmp.childNodes ); - - // Fix #12392 for WebKit and IE > 9 - tmp.textContent = ""; - - // Fix #12392 for oldIE - while ( tmp.firstChild ) { - tmp.removeChild( tmp.firstChild ); - } - - // Remember the top-level container for proper cleanup - tmp = safe.lastChild; - } - } - } - - // Fix #11356: Clear elements from safeFragment - if ( tmp ) { - safe.removeChild( tmp ); - } - - // Reset defaultChecked for any radios and checkboxes - // about to be appended to the DOM in IE 6/7 (#8060) - if ( !jQuery.support.appendChecked ) { - jQuery.grep( getAll( ret, "input" ), fixDefaultChecked ); - } - - if ( fragment ) { - for ( i = 0; (elem = ret[i]) != null; i++ ) { - safe = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - // #4087 - If origin and destination elements are the same, and this is - // that element, do not append to fragment - if ( !selection || jQuery.inArray( elem, selection ) === -1 ) { - fragment.appendChild( elem ); - } - tmp = getAll( elem, "script" ); - - // Preserve script evaluation history - if ( safe ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - for ( j = 0; (elem = tmp[j]) != null; j++ ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - } - - elem = tmp = safe = null; - - return ret; - }, - - cleanData: function( elems, /* internal */ acceptData ) { - var data, id, elem, type, - i = 0, - internalKey = jQuery.expando, - cache = jQuery.cache, - deleteExpando = jQuery.support.deleteExpando, - special = jQuery.event.special; - - for ( ; (elem = elems[i]) != null; i++ ) { - - if ( acceptData || jQuery.acceptData( elem ) ) { - - id = elem[ internalKey ]; - data = id && cache[ id ]; - - if ( data ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Remove cache only if it was not already removed by jQuery.event.remove - if ( cache[ id ] ) { - - delete cache[ id ]; - - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( deleteExpando ) { - delete elem[ internalKey ]; - - } else if ( elem.removeAttribute ) { - elem.removeAttribute( internalKey ); - - } else { - elem[ internalKey ] = null; - } - - core_deletedIds.push( id ); - } - } - } - } - } -}); diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 86b26e040..d9b014187 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -395,13 +395,13 @@ var testAppendForObject = function( valueObj, isFragment ) { var testAppend = function( valueObj ) { - expect( 59 ); + expect( 77 ); testAppendForObject( valueObj, false ); testAppendForObject( valueObj, true ); var defaultText, result, message, iframe, iframeDoc, j, d, - $input, $radioChecked, $radioUnchecked, $radioParent; + $input, $radioChecked, $radioUnchecked, $radioParent, $map, $table; defaultText = "Try them out:"; result = jQuery("#first").append( valueObj("buga") ); @@ -446,18 +446,29 @@ var testAppend = function( valueObj ) { jQuery("
").appendTo("#form").append( valueObj("test") ); t( "Append legend", "#legend", [ "legend" ] ); + $map = jQuery("").append( valueObj("jQuery") ); + + equal( $map[ 0 ].childNodes.length, 1, "The area was inserted." ); + equal( $map[ 0 ].firstChild.nodeName.toLowerCase(), "area", "The area was inserted." ); + jQuery("#select1").append( valueObj("") ); equal( jQuery("#select1 option:last").text(), "Test", "Appending OPTION (all caps)" ); - jQuery("#table").append( valueObj("
") ); - equal( jQuery("#table colgroup").length, 1, "Append colgroup" ); + jQuery("#select1").append( valueObj("") ); + equal( jQuery("#select1 optgroup").attr("label"), "optgroup", "Label attribute in newly inserted optgroup is correct" ); + equal( jQuery("#select1 option:last").text(), "optgroup", "Appending optgroup" ); + + $table = jQuery("#table"); + + jQuery.each( "thead tbody tfoot colgroup caption tr th td".split(" "), function( i, name ) { + $table.append( valueObj( "<" + name + "/>" ) ); + equal( $table.find( name ).length, 1, "Append " + name ); + ok( jQuery.clean( ["<" + name + "/>"] ).length, name + " wrapped correctly" ); + }); jQuery("#table colgroup").append( valueObj("") ); equal( jQuery("#table colgroup col").length, 1, "Append col" ); - jQuery("#table").append( valueObj("") ); - equal( jQuery("#table caption").length, 1, "Append caption" ); - jQuery("#form") .append( valueObj("") ) .append( valueObj("") ); @@ -2240,9 +2251,19 @@ test( "insertAfter, insertBefore, etc do not work when destination is original e }); test( "Index for function argument should be received (#13094)", 2, function() { - var i = 0; + var i = 0; + + jQuery("
").before(function( index ) { + equal( index, i++, "Index should be correct" ); + }); - jQuery("
").before(function( index ) { - equal( index, i++, "Index should be correct" ); - }); +}); + +test( "Make sure jQuery.fn.remove can work on elements in documentFragment", 1, function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement("div") ); + + jQuery( div ).remove(); + + equal( fragment.childNodes.length, 0, "div element was removed from documentFragment" ); });