Commit e78d3a7e authored by Colin Snover's avatar Colin Snover

Merge in data_nocollide branch. Fixes #6968, improves unit testing framework...

Merge in data_nocollide branch. Fixes #6968, improves unit testing framework checks for leaky stuff.
parents f01ef93a 57cc182a
...@@ -133,11 +133,11 @@ jQuery.fn.extend({ ...@@ -133,11 +133,11 @@ jQuery.fn.extend({
} else if ( type === "undefined" || type === "boolean" ) { } else if ( type === "undefined" || type === "boolean" ) {
if ( this.className ) { if ( this.className ) {
// store className if set // store className if set
jQuery.data( this, "__className__", this.className ); jQuery._data( this, "__className__", this.className );
} }
// toggle whole className // toggle whole className
this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
} }
}); });
}, },
......
(function( jQuery ) { (function( jQuery ) {
var windowData = {}, var rbrace = /^(?:\{.*\}|\[.*\])$/;
rbrace = /^(?:\{.*\}|\[.*\])$/;
jQuery.extend({ jQuery.extend({
cache: {}, cache: {},
...@@ -23,110 +22,170 @@ jQuery.extend({ ...@@ -23,110 +22,170 @@ jQuery.extend({
}, },
hasData: function( elem ) { hasData: function( elem ) {
if ( elem.nodeType ) { elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
elem = jQuery.cache[ elem[jQuery.expando] ];
}
return !!elem && !jQuery.isEmptyObject(elem); return !!elem && !jQuery.isEmptyObject(elem);
}, },
data: function( elem, name, data ) { data: function( elem, name, data, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) { if ( !jQuery.acceptData( elem ) ) {
return; return;
} }
elem = elem == window ? var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
windowData :
elem; // We have to handle DOM nodes and JS objects differently because IE6-7
// can't GC object references properly across the DOM-JS boundary
isNode = elem.nodeType,
// Only DOM nodes need the global jQuery cache; JS object data is
// attached directly to the object so GC can occur automatically
cache = isNode ? jQuery.cache : elem,
var isNode = elem.nodeType, // Only defining an ID for JS objects if its cache already exists allows
id = isNode ? elem[ jQuery.expando ] : null, // the code to shortcut on the same path as a DOM node with no cache
cache = jQuery.cache, thisCache; id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
if ( isNode && !id && typeof name === "string" && data === undefined ) { // Avoid doing any more work than we need to when trying to get data on an
// object that has no data at all
if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
return; return;
} }
// Get the data from the object directly if ( !id ) {
if ( !isNode ) { // Only DOM nodes need a new unique ID for each element since their data
cache = elem; // ends up in the global cache
if ( isNode ) {
elem[ jQuery.expando ] = id = ++jQuery.uuid;
} else {
id = jQuery.expando;
}
}
// Compute a unique ID for the element if ( !cache[ id ] ) {
} else if ( !id ) { cache[ id ] = {};
elem[ jQuery.expando ] = id = ++jQuery.uuid;
} }
// Avoid generating a new cache unless none exists and we // An object can be passed to jQuery.data instead of a key/value pair; this gets
// want to manipulate it. // shallow copied over onto the existing cache
if ( typeof name === "object" ) { if ( typeof name === "object" ) {
if ( isNode ) { if ( pvt ) {
cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
} else {
cache[ id ] = jQuery.extend(cache[ id ], name); cache[ id ] = jQuery.extend(cache[ id ], name);
}
}
} else { thisCache = cache[ id ];
jQuery.extend( cache, name );
// Internal jQuery data is stored in a separate object inside the object's data
// cache in order to avoid key collisions between internal data and user-defined
// data
if ( pvt ) {
if ( !thisCache[ internalKey ] ) {
thisCache[ internalKey ] = {};
} }
} else if ( isNode && !cache[ id ] ) { thisCache = thisCache[ internalKey ];
cache[ id ] = {};
} }
thisCache = isNode ? cache[ id ] : cache;
// Prevent overriding the named cache with undefined values
if ( data !== undefined ) { if ( data !== undefined ) {
thisCache[ name ] = data; thisCache[ name ] = data;
} }
return typeof name === "string" ? thisCache[ name ] : thisCache; // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
// not attempt to inspect the internal events object using jQuery.data, as this
// internal data object is undocumented and subject to change.
if ( name === "events" && !thisCache[name] ) {
return thisCache[ internalKey ] && thisCache[ internalKey ].events;
}
return getByName ? thisCache[ name ] : thisCache;
}, },
removeData: function( elem, name ) { removeData: function( elem, name, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) { if ( !jQuery.acceptData( elem ) ) {
return; return;
} }
elem = elem == window ? var internalKey = jQuery.expando, isNode = elem.nodeType,
windowData :
elem; // See jQuery.data for more information
cache = isNode ? jQuery.cache : elem,
var isNode = elem.nodeType, // See jQuery.data for more information
id = isNode ? elem[ jQuery.expando ] : elem, id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
cache = jQuery.cache,
thisCache = isNode ? cache[ id ] : id; // If there is already no cache entry for this object, there is no
// purpose in continuing
if ( !cache[ id ] ) {
return;
}
// If we want to remove a specific section of the element's data
if ( name ) { if ( name ) {
var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
if ( thisCache ) { if ( thisCache ) {
// Remove the section of cache data
delete thisCache[ name ]; delete thisCache[ name ];
// If we've removed all the data, remove the element's cache // If there is no data left in the cache, we want to continue
if ( isNode && jQuery.isEmptyObject(thisCache) ) { // and let the cache object itself get destroyed
jQuery.removeData( elem ); if ( !jQuery.isEmptyObject(thisCache) ) {
return;
} }
} }
}
// See jQuery.data for more information
if ( pvt ) {
delete cache[ id ][ internalKey ];
// Don't destroy the parent cache unless the internal data object
// had been the only thing left in it
if ( !jQuery.isEmptyObject(cache[ id ]) ) {
return;
}
}
var internalCache = cache[ id ][ internalKey ];
// Otherwise, we want to remove all of the element's data // Browsers that fail expando deletion also refuse to delete expandos on
// the window, but it will allow it on all other JS objects; other browsers
// don't care
if ( jQuery.support.deleteExpando || cache != window ) {
delete cache[ id ];
} else { } else {
if ( isNode && jQuery.support.deleteExpando ) { cache[ id ] = null;
delete elem[ jQuery.expando ]; }
// We destroyed the entire user cache at once because it's faster than
// iterating through each key, but we need to continue to persist internal
// data if it existed
if ( internalCache ) {
cache[ id ] = {};
cache[ id ][ internalKey ] = internalCache;
// Otherwise, we need to eliminate the expando on the node to avoid
// false lookups in the cache for entries that no longer exist
} else if ( isNode ) {
// 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 ( jQuery.support.deleteExpando ) {
delete elem[ jQuery.expando ];
} else if ( elem.removeAttribute ) { } else if ( elem.removeAttribute ) {
elem.removeAttribute( jQuery.expando ); elem.removeAttribute( jQuery.expando );
// Completely remove the data cache
} else if ( isNode ) {
delete cache[ id ];
// Remove all fields from the object
} else { } else {
for ( var n in elem ) { elem[ jQuery.expando ] = null;
delete elem[ n ];
}
} }
} }
}, },
// For internal use only.
_data: function( elem, name, data ) {
return jQuery.data( elem, name, data, true );
},
// A method for determining if a DOM node can handle the data expando // A method for determining if a DOM node can handle the data expando
acceptData: function( elem ) { acceptData: function( elem ) {
if ( elem.nodeName ) { if ( elem.nodeName ) {
......
...@@ -27,7 +27,7 @@ jQuery.fn.extend({ ...@@ -27,7 +27,7 @@ jQuery.fn.extend({
// Reset the inline display of this element to learn if it is // Reset the inline display of this element to learn if it is
// being hidden by cascaded rules or not // being hidden by cascaded rules or not
if ( !jQuery.data(elem, "olddisplay") && display === "none" ) { if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
display = elem.style.display = ""; display = elem.style.display = "";
} }
...@@ -35,7 +35,7 @@ jQuery.fn.extend({ ...@@ -35,7 +35,7 @@ jQuery.fn.extend({
// in a stylesheet to whatever the default browser style is // in a stylesheet to whatever the default browser style is
// for such an element // for such an element
if ( display === "" && jQuery.css( elem, "display" ) === "none" ) { if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName)); jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
} }
} }
...@@ -46,7 +46,7 @@ jQuery.fn.extend({ ...@@ -46,7 +46,7 @@ jQuery.fn.extend({
display = elem.style.display; display = elem.style.display;
if ( display === "" || display === "none" ) { if ( display === "" || display === "none" ) {
elem.style.display = jQuery.data(elem, "olddisplay") || ""; elem.style.display = jQuery._data(elem, "olddisplay") || "";
} }
} }
...@@ -62,8 +62,8 @@ jQuery.fn.extend({ ...@@ -62,8 +62,8 @@ jQuery.fn.extend({
for ( var i = 0, j = this.length; i < j; i++ ) { for ( var i = 0, j = this.length; i < j; i++ ) {
var display = jQuery.css( this[i], "display" ); var display = jQuery.css( this[i], "display" );
if ( display !== "none" && !jQuery.data( this[i], "olddisplay" ) ) { if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
jQuery.data( this[i], "olddisplay", display ); jQuery._data( this[i], "olddisplay", display );
} }
} }
......
...@@ -8,7 +8,8 @@ var rnamespaces = /\.(.*)$/, ...@@ -8,7 +8,8 @@ var rnamespaces = /\.(.*)$/,
fcleanup = function( nm ) { fcleanup = function( nm ) {
return nm.replace(rescape, "\\$&"); return nm.replace(rescape, "\\$&");
}, },
focusCounts = { focusin: 0, focusout: 0 }; focusCounts = { focusin: 0, focusout: 0 },
eventKey = "events";
/* /*
* A number of helper functions used for managing events. * A number of helper functions used for managing events.
...@@ -50,7 +51,7 @@ jQuery.event = { ...@@ -50,7 +51,7 @@ jQuery.event = {
} }
// Init the element's event structure // Init the element's event structure
var elemData = jQuery.data( elem ); var elemData = jQuery._data( elem );
// If no elemData is found then we must be trying to bind to one of the // If no elemData is found then we must be trying to bind to one of the
// banned noData elements // banned noData elements
...@@ -58,10 +59,7 @@ jQuery.event = { ...@@ -58,10 +59,7 @@ jQuery.event = {
return; return;
} }
// Use a key less likely to result in collisions for plain JS objects. var events = elemData[ eventKey ],
// Fixes bug #7150.
var eventKey = elem.nodeType ? "events" : "__events__",
events = elemData[ eventKey ],
eventHandle = elemData.handle; eventHandle = elemData.handle;
if ( typeof events === "function" ) { if ( typeof events === "function" ) {
...@@ -177,8 +175,7 @@ jQuery.event = { ...@@ -177,8 +175,7 @@ jQuery.event = {
} }
var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
eventKey = elem.nodeType ? "events" : "__events__", elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
elemData = jQuery.data( elem ),
events = elemData && elemData[ eventKey ]; events = elemData && elemData[ eventKey ];
if ( !elemData || !events ) { if ( !elemData || !events ) {
...@@ -290,10 +287,10 @@ jQuery.event = { ...@@ -290,10 +287,10 @@ jQuery.event = {
delete elemData.handle; delete elemData.handle;
if ( typeof elemData === "function" ) { if ( typeof elemData === "function" ) {
jQuery.removeData( elem, eventKey ); jQuery.removeData( elem, eventKey, true );
} else if ( jQuery.isEmptyObject( elemData ) ) { } else if ( jQuery.isEmptyObject( elemData ) ) {
jQuery.removeData( elem ); jQuery.removeData( elem, undefined, true );
} }
} }
}, },
...@@ -325,9 +322,16 @@ jQuery.event = { ...@@ -325,9 +322,16 @@ jQuery.event = {
// Only trigger if we've ever bound an event for it // Only trigger if we've ever bound an event for it
if ( jQuery.event.global[ type ] ) { if ( jQuery.event.global[ type ] ) {
// XXX This code smells terrible. event.js should not be directly
// inspecting the data cache
jQuery.each( jQuery.cache, function() { jQuery.each( jQuery.cache, function() {
if ( this.events && this.events[type] ) { // internalKey variable is just used to make it easier to find
jQuery.event.trigger( event, data, this.handle.elem ); // and potentially change this stuff later; currently it just
// points to jQuery.expando
var internalKey = jQuery.expando,
internalCache = this[ internalKey ];
if ( internalCache && internalCache.events && internalCache.events[type] ) {
jQuery.event.trigger( event, data, internalCache.handle.elem );
} }
}); });
} }
...@@ -353,8 +357,8 @@ jQuery.event = { ...@@ -353,8 +357,8 @@ jQuery.event = {
// Trigger the event, it is assumed that "handle" is a function // Trigger the event, it is assumed that "handle" is a function
var handle = elem.nodeType ? var handle = elem.nodeType ?
jQuery.data( elem, "handle" ) : jQuery._data( elem, "handle" ) :
(jQuery.data( elem, "__events__" ) || {}).handle; (jQuery._data( elem, eventKey ) || {}).handle;
if ( handle ) { if ( handle ) {
handle.apply( elem, data ); handle.apply( elem, data );
...@@ -432,7 +436,7 @@ jQuery.event = { ...@@ -432,7 +436,7 @@ jQuery.event = {
event.namespace = event.namespace || namespace_sort.join("."); event.namespace = event.namespace || namespace_sort.join(".");
events = jQuery.data(this, this.nodeType ? "events" : "__events__"); events = jQuery._data(this, eventKey);
if ( typeof events === "function" ) { if ( typeof events === "function" ) {
events = events.events; events = events.events;
...@@ -787,12 +791,12 @@ if ( !jQuery.support.changeBubbles ) { ...@@ -787,12 +791,12 @@ if ( !jQuery.support.changeBubbles ) {
return; return;
} }
data = jQuery.data( elem, "_change_data" ); data = jQuery._data( elem, "_change_data" );
val = getVal(elem); val = getVal(elem);
// the current data will be also retrieved by beforeactivate // the current data will be also retrieved by beforeactivate
if ( e.type !== "focusout" || elem.type !== "radio" ) { if ( e.type !== "focusout" || elem.type !== "radio" ) {
jQuery.data( elem, "_change_data", val ); jQuery._data( elem, "_change_data", val );
} }
if ( data === undefined || val === data ) { if ( data === undefined || val === data ) {
...@@ -837,7 +841,7 @@ if ( !jQuery.support.changeBubbles ) { ...@@ -837,7 +841,7 @@ if ( !jQuery.support.changeBubbles ) {
// information // information
beforeactivate: function( e ) { beforeactivate: function( e ) {
var elem = e.target; var elem = e.target;
jQuery.data( elem, "_change_data", getVal(elem) ); jQuery._data( elem, "_change_data", getVal(elem) );
} }
}, },
...@@ -986,8 +990,8 @@ jQuery.fn.extend({ ...@@ -986,8 +990,8 @@ jQuery.fn.extend({
return this.click( jQuery.proxy( fn, function( event ) { return this.click( jQuery.proxy( fn, function( event ) {
// Figure out which function to execute // Figure out which function to execute
var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
// Make sure that clicks stop // Make sure that clicks stop
event.preventDefault(); event.preventDefault();
...@@ -1075,7 +1079,7 @@ function liveHandler( event ) { ...@@ -1075,7 +1079,7 @@ function liveHandler( event ) {
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
elems = [], elems = [],
selectors = [], selectors = [],
events = jQuery.data( this, this.nodeType ? "events" : "__events__" ); events = jQuery._data( this, eventKey );
if ( typeof events === "function" ) { if ( typeof events === "function" ) {
events = events.events; events = events.events;
......
...@@ -346,7 +346,7 @@ jQuery.fn.extend({ ...@@ -346,7 +346,7 @@ jQuery.fn.extend({
table ? table ?
root(this[i], first) : root(this[i], first) :
this[i], this[i],
i > 0 || results.cacheable || this.length > 1 ? i > 0 || results.cacheable || (this.length > 1 && i > 0) ?
jQuery(fragment).clone(true)[0] : jQuery(fragment).clone(true)[0] :
fragment fragment
); );
...@@ -381,17 +381,24 @@ function cloneCopyEvent(orig, ret) { ...@@ -381,17 +381,24 @@ function cloneCopyEvent(orig, ret) {
throw "Cloned data mismatch"; throw "Cloned data mismatch";
} }
var oldData = jQuery.data( orig[nodeIndex] ), var internalKey = jQuery.expando,
curData = jQuery.data( this, oldData ), oldData = jQuery.data( orig[nodeIndex] ),
events = oldData && oldData.events; curData = jQuery.data( this, oldData );
if ( events ) { // Switch to use the internal data object, if it exists, for the next
delete curData.handle; // stage of data copying
curData.events = {}; if ( (oldData = oldData[ internalKey ]) ) {
var events = oldData.events;
curData = curData[ internalKey ] = jQuery.extend({}, oldData);
for ( var type in events ) { if ( events ) {
for ( var i = 0, l = events[ type ].length; i < l; i++ ) { delete curData.handle;
jQuery.event.add( this, type, events[ type ][ i ], events[ type ][ i ].data ); curData.events = {};
for ( var type in events ) {
for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
jQuery.event.add( this, type, events[ type ][ i ], events[ type ][ i ].data );
}
} }
} }
} }
...@@ -608,8 +615,7 @@ jQuery.extend({ ...@@ -608,8 +615,7 @@ jQuery.extend({
}, },
cleanData: function( elems ) { cleanData: function( elems ) {
var data, id, cache = jQuery.cache, var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
special = jQuery.event.special,
deleteExpando = jQuery.support.deleteExpando; deleteExpando = jQuery.support.deleteExpando;
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
...@@ -620,13 +626,14 @@ jQuery.extend({ ...@@ -620,13 +626,14 @@ jQuery.extend({
id = elem[ jQuery.expando ]; id = elem[ jQuery.expando ];
if ( id ) { if ( id ) {
data = cache[ id ]; data = cache[ id ] && cache[ id ][ internalKey ];
if ( data && data.events ) { if ( data && data.events ) {
for ( var type in data.events ) { for ( var type in data.events ) {
if ( special[ type ] ) { if ( special[ type ] ) {
jQuery.event.remove( elem, type ); jQuery.event.remove( elem, type );
// This is a shortcut to avoid jQuery.event.remove's overhead
} else { } else {
jQuery.removeEvent( elem, type, data.handle ); jQuery.removeEvent( elem, type, data.handle );
} }
......
...@@ -7,7 +7,7 @@ jQuery.extend({ ...@@ -7,7 +7,7 @@ jQuery.extend({
} }
type = (type || "fx") + "queue"; type = (type || "fx") + "queue";
var q = jQuery.data( elem, type ); var q = jQuery._data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup // Speed up dequeue by getting out quickly if this is just a lookup
if ( !data ) { if ( !data ) {
...@@ -15,7 +15,7 @@ jQuery.extend({ ...@@ -15,7 +15,7 @@ jQuery.extend({
} }
if ( !q || jQuery.isArray(data) ) { if ( !q || jQuery.isArray(data) ) {
q = jQuery.data( elem, type, jQuery.makeArray(data) ); q = jQuery._data( elem, type, jQuery.makeArray(data) );
} else { } else {
q.push( data ); q.push( data );
...@@ -46,6 +46,10 @@ jQuery.extend({ ...@@ -46,6 +46,10 @@ jQuery.extend({
jQuery.dequeue(elem, type); jQuery.dequeue(elem, type);
}); });
} }
if ( !queue.length ) {
jQuery.removeData( elem, type + "queue", true );
}
} }
}); });
......
...@@ -45,3 +45,52 @@ function t(a,b,c) { ...@@ -45,3 +45,52 @@ function t(a,b,c) {
function url(value) { function url(value) {
return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000); return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000);
} }
(function () {
// Store the old counts so that we only assert on tests that have actually leaked,
// instead of asserting every time a test has leaked sometime in the past
var oldCacheLength = 0,
oldFragmentsLength = 0,
oldTimersLength = 0,
oldActive = 0;
/**
* Ensures that tests have cleaned up properly after themselves. Should be passed as the
* teardown function on all modules' lifecycle object.
*/
this.moduleTeardown = function () {
var i, fragmentsLength = 0, cacheLength = 0;
// Allow QUnit.reset to clean up any attached elements before checking for leaks
QUnit.reset();
for ( i in jQuery.cache ) {
++cacheLength;
}
jQuery.fragments = {};
for ( i in jQuery.fragments ) {
++fragmentsLength;
}
// Because QUnit doesn't have a mechanism for retrieving the number of expected assertions for a test,
// if we unconditionally assert any of these, the test will fail with too many assertions :|
if ( cacheLength !== oldCacheLength ) {
equals( cacheLength, oldCacheLength, "No unit tests leak memory in jQuery.cache" );
oldCacheLength = cacheLength;
}
if ( fragmentsLength !== oldFragmentsLength ) {
equals( fragmentsLength, oldFragmentsLength, "No unit tests leak memory in jQuery.fragments" );
oldFragmentsLength = fragmentsLength;
}
if ( jQuery.timers.length !== oldTimersLength ) {
equals( jQuery.timers.length, oldTimersLength, "No timers are still running" );
oldTimersLength = jQuery.timers.length;
}
if ( jQuery.active !== oldActive ) {
equals( jQuery.active, 0, "No AJAX requests are still active" );
oldActive = jQuery.active;
}
}
}());
\ No newline at end of file
...@@ -264,7 +264,7 @@ Z</textarea> ...@@ -264,7 +264,7 @@ Z</textarea>
<div id="slidetoggleout" class='chain test out'>slideToggleOut<div>slideToggleOut</div></div> <div id="slidetoggleout" class='chain test out'>slideToggleOut<div>slideToggleOut</div></div>
<div id="fadetogglein" class='chain test'>fadeToggleIn<div>fadeToggleIn</div></div> <div id="fadetogglein" class='chain test'>fadeToggleIn<div>fadeToggleIn</div></div>
<div id="fadetoggleout" class='chain test out'>fadeToggleOut<div>fadeToggleOut</div></div> <div id="fadetoggleout" class='chain test out'>fadeToggleOut<div>fadeToggleOut</div></div>
<div id="fadeto" class='chain test'>fadeTo<div>fadeTo</div></div> <div id="fadeto" class='chain test'>fadeTo<div>fadeTo</div></div>
</div> </div>
......
module("ajax"); module("ajax", { teardown: moduleTeardown });
// Safari 3 randomly crashes when running these tests, // Safari 3 randomly crashes when running these tests,
// but only in the full suite - you can run just the Ajax // but only in the full suite - you can run just the Ajax
......
module("attributes"); module("attributes", { teardown: moduleTeardown });
var bareObj = function(value) { return value; }; var bareObj = function(value) { return value; };
var functionReturningObj = function(value) { return (function() { return value; }); }; var functionReturningObj = function(value) { return (function() { return value; }); };
...@@ -703,12 +703,12 @@ var testToggleClass = function(valueObj) { ...@@ -703,12 +703,12 @@ var testToggleClass = function(valueObj) {
// toggleClass storage // toggleClass storage
e.toggleClass(true); e.toggleClass(true);
ok( e.get(0).className === "", "Assert class is empty (data was empty)" ); ok( e[0].className === "", "Assert class is empty (data was empty)" );
e.addClass("testD testE"); e.addClass("testD testE");
ok( e.is(".testD.testE"), "Assert class present" ); ok( e.is(".testD.testE"), "Assert class present" );
e.toggleClass(); e.toggleClass();
ok( !e.is(".testD.testE"), "Assert class not present" ); ok( !e.is(".testD.testE"), "Assert class not present" );
ok( e.data('__className__') === 'testD testE', "Assert data was stored" ); ok( jQuery._data(e[0], '__className__') === 'testD testE', "Assert data was stored" );
e.toggleClass(); e.toggleClass();
ok( e.is(".testD.testE"), "Assert class present (restored from data)" ); ok( e.is(".testD.testE"), "Assert class present (restored from data)" );
e.toggleClass(false); e.toggleClass(false);
...@@ -720,11 +720,9 @@ var testToggleClass = function(valueObj) { ...@@ -720,11 +720,9 @@ var testToggleClass = function(valueObj) {
e.toggleClass(); e.toggleClass();
ok( e.is(".testD.testE"), "Assert class present (restored from data)" ); ok( e.is(".testD.testE"), "Assert class present (restored from data)" );
// Cleanup // Cleanup
e.removeClass("testD"); e.removeClass("testD");
e.removeData('__className__'); jQuery.removeData(e[0], '__className__', true);
}; };
test("toggleClass(String|boolean|undefined[, boolean])", function() { test("toggleClass(String|boolean|undefined[, boolean])", function() {
...@@ -785,7 +783,7 @@ test("toggleClass(Fucntion[, boolean]) with incoming value", function() { ...@@ -785,7 +783,7 @@ test("toggleClass(Fucntion[, boolean]) with incoming value", function() {
// Cleanup // Cleanup
e.removeClass("test"); e.removeClass("test");
e.removeData('__className__'); jQuery.removeData(e[0], '__className__', true);
}); });
test("addClass, removeClass, hasClass", function() { test("addClass, removeClass, hasClass", function() {
......
module("core"); module("core", { teardown: moduleTeardown });
test("Basic requirements", function() { test("Basic requirements", function() {
expect(7); expect(7);
...@@ -85,10 +85,16 @@ test("jQuery()", function() { ...@@ -85,10 +85,16 @@ test("jQuery()", function() {
exec = true; exec = true;
elem.click(); elem.click();
// manually clean up detached elements
elem.remove();
for ( var i = 0; i < 3; ++i ) { for ( var i = 0; i < 3; ++i ) {
elem = jQuery("<input type='text' value='TEST' />"); elem = jQuery("<input type='text' value='TEST' />");
} }
equals( elem[0].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" ); equals( elem[0].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" );
// manually clean up detached elements
elem.remove();
}); });
test("selector state", function() { test("selector state", function() {
......
module("css"); module("css", { teardown: moduleTeardown });
test("css(String|Hash)", function() { test("css(String|Hash)", function() {
expect(41); expect(41);
......
This diff is collapsed.
module("dimensions"); module("dimensions", { teardown: moduleTeardown });
function pass( val ) { function pass( val ) {
return val; return val;
...@@ -33,6 +33,8 @@ function testWidth( val ) { ...@@ -33,6 +33,8 @@ function testWidth( val ) {
var blah = jQuery("blah"); var blah = jQuery("blah");
equals( blah.width( val(10) ), blah, "Make sure that setting a width on an empty set returns the set." ); equals( blah.width( val(10) ), blah, "Make sure that setting a width on an empty set returns the set." );
equals( blah.width(), null, "Make sure 'null' is returned on an empty set"); equals( blah.width(), null, "Make sure 'null' is returned on an empty set");
jQuery.removeData($div[0], 'olddisplay', true);
} }
test("width()", function() { test("width()", function() {
...@@ -80,6 +82,8 @@ function testHeight( val ) { ...@@ -80,6 +82,8 @@ function testHeight( val ) {
var blah = jQuery("blah"); var blah = jQuery("blah");
equals( blah.height( val(10) ), blah, "Make sure that setting a height on an empty set returns the set." ); equals( blah.height( val(10) ), blah, "Make sure that setting a height on an empty set returns the set." );
equals( blah.height(), null, "Make sure 'null' is returned on an empty set"); equals( blah.height(), null, "Make sure 'null' is returned on an empty set");
jQuery.removeData($div[0], 'olddisplay', true);
} }
test("height()", function() { test("height()", function() {
...@@ -126,6 +130,9 @@ test("innerWidth()", function() { ...@@ -126,6 +130,9 @@ test("innerWidth()", function() {
// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.innerWidth(), 0, "Make sure that disconnected nodes are handled." ); equals( div.innerWidth(), 0, "Make sure that disconnected nodes are handled." );
div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });
test("innerHeight()", function() { test("innerHeight()", function() {
...@@ -152,6 +159,9 @@ test("innerHeight()", function() { ...@@ -152,6 +159,9 @@ test("innerHeight()", function() {
// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.innerHeight(), 0, "Make sure that disconnected nodes are handled." ); equals( div.innerHeight(), 0, "Make sure that disconnected nodes are handled." );
div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });
test("outerWidth()", function() { test("outerWidth()", function() {
...@@ -179,6 +189,9 @@ test("outerWidth()", function() { ...@@ -179,6 +189,9 @@ test("outerWidth()", function() {
// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.outerWidth(), 0, "Make sure that disconnected nodes are handled." ); equals( div.outerWidth(), 0, "Make sure that disconnected nodes are handled." );
div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });
test("outerHeight()", function() { test("outerHeight()", function() {
...@@ -205,4 +218,7 @@ test("outerHeight()", function() { ...@@ -205,4 +218,7 @@ test("outerHeight()", function() {
// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.outerHeight(), 0, "Make sure that disconnected nodes are handled." ); equals( div.outerHeight(), 0, "Make sure that disconnected nodes are handled." );
div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });
module("effects"); module("effects", { teardown: moduleTeardown });
test("sanity check", function() { test("sanity check", function() {
expect(1); expect(1);
...@@ -14,7 +14,7 @@ test("show()", function() { ...@@ -14,7 +14,7 @@ test("show()", function() {
equals( hiddendiv.css("display"), "block", "Make sure a pre-hidden div is visible." ); equals( hiddendiv.css("display"), "block", "Make sure a pre-hidden div is visible." );
var div = jQuery("<div>").hide().appendTo("body").show(); var div = jQuery("<div>").hide().appendTo("#main").show();
equal( div.css("display"), "block", "Make sure pre-hidden divs show" ); equal( div.css("display"), "block", "Make sure pre-hidden divs show" );
...@@ -403,13 +403,16 @@ test("animate duration 0", function() { ...@@ -403,13 +403,16 @@ test("animate duration 0", function() {
$elem.hide(0, function(){ $elem.hide(0, function(){
ok(true, "Hide callback with no duration"); ok(true, "Hide callback with no duration");
}); });
// manually clean up detached elements
$elem.remove();
}); });
test("animate hyphenated properties", function(){ test("animate hyphenated properties", function(){
expect(1); expect(1);
stop(); stop();
jQuery("#nothiddendiv") jQuery("#foo")
.css("font-size", 10) .css("font-size", 10)
.animate({"font-size": 20}, 200, function(){ .animate({"font-size": 20}, 200, function(){
equals( this.style.fontSize, "20px", "The font-size property was animated." ); equals( this.style.fontSize, "20px", "The font-size property was animated." );
...@@ -433,7 +436,7 @@ test("stop()", function() { ...@@ -433,7 +436,7 @@ test("stop()", function() {
expect(3); expect(3);
stop(); stop();
var $foo = jQuery("#nothiddendiv"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();
...@@ -446,6 +449,8 @@ test("stop()", function() { ...@@ -446,6 +449,8 @@ test("stop()", function() {
nw = $foo.width(); nw = $foo.width();
notEqual( nw, w, "Stop didn't reset the animation " + nw + "px " + w + "px"); notEqual( nw, w, "Stop didn't reset the animation " + nw + "px " + w + "px");
setTimeout(function(){ setTimeout(function(){
$foo.removeData();
$foo.removeData(undefined, true);
equals( nw, $foo.width(), "The animation didn't continue" ); equals( nw, $foo.width(), "The animation didn't continue" );
start(); start();
}, 100); }, 100);
...@@ -456,7 +461,7 @@ test("stop() - several in queue", function() { ...@@ -456,7 +461,7 @@ test("stop() - several in queue", function() {
expect(3); expect(3);
stop(); stop();
var $foo = jQuery("#nothiddendivchild"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();
...@@ -481,7 +486,7 @@ test("stop(clearQueue)", function() { ...@@ -481,7 +486,7 @@ test("stop(clearQueue)", function() {
expect(4); expect(4);
stop(); stop();
var $foo = jQuery("#nothiddendiv"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();
...@@ -508,7 +513,7 @@ test("stop(clearQueue, gotoEnd)", function() { ...@@ -508,7 +513,7 @@ test("stop(clearQueue, gotoEnd)", function() {
expect(1); expect(1);
stop(); stop();
var $foo = jQuery("#nothiddendivchild"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();
...@@ -536,7 +541,7 @@ test("stop(clearQueue, gotoEnd)", function() { ...@@ -536,7 +541,7 @@ test("stop(clearQueue, gotoEnd)", function() {
test("toggle()", function() { test("toggle()", function() {
expect(6); expect(6);
var x = jQuery("#nothiddendiv"); var x = jQuery("#foo");
ok( x.is(":visible"), "is visible" ); ok( x.is(":visible"), "is visible" );
x.toggle(); x.toggle();
ok( x.is(":hidden"), "is hidden" ); ok( x.is(":hidden"), "is hidden" );
...@@ -737,6 +742,9 @@ jQuery.each( { ...@@ -737,6 +742,9 @@ jQuery.each( {
} }
} }
// manually remove generated element
jQuery(this).remove();
start(); start();
}); });
}); });
...@@ -763,6 +771,10 @@ jQuery.checkState = function(){ ...@@ -763,6 +771,10 @@ jQuery.checkState = function(){
var cur = self.style[ c ] || jQuery.css(self, c); var cur = self.style[ c ] || jQuery.css(self, c);
equals( cur, v, "Make sure that " + c + " is reset (Old: " + v + " Cur: " + cur + ")"); equals( cur, v, "Make sure that " + c + " is reset (Old: " + v + " Cur: " + cur + ")");
}); });
// manually clean data on modified element
jQuery.removeData(this, 'olddisplay', true);
start(); start();
} }
...@@ -829,9 +841,6 @@ jQuery.makeTest = function( text ){ ...@@ -829,9 +841,6 @@ jQuery.makeTest = function( text ){
jQuery("<h4></h4>") jQuery("<h4></h4>")
.text( text ) .text( text )
.appendTo("#fx-tests") .appendTo("#fx-tests")
.click(function(){
jQuery(this).next().toggle();
})
.after( elem ); .after( elem );
return elem; return elem;
...@@ -895,7 +904,7 @@ test("hide hidden elements (bug #7141)", function() { ...@@ -895,7 +904,7 @@ test("hide hidden elements (bug #7141)", function() {
var div = jQuery("<div style='display:none'></div>").appendTo("#main"); var div = jQuery("<div style='display:none'></div>").appendTo("#main");
equals( div.css("display"), "none", "Element is hidden by default" ); equals( div.css("display"), "none", "Element is hidden by default" );
div.hide(); div.hide();
ok( !div.data("olddisplay"), "olddisplay is undefined after hiding an already-hidden element" ); ok( !jQuery._data(div, "olddisplay"), "olddisplay is undefined after hiding an already-hidden element" );
div.show(); div.show();
equals( div.css("display"), "block", "Show a double-hidden element" ); equals( div.css("display"), "block", "Show a double-hidden element" );
...@@ -910,7 +919,7 @@ test("hide hidden elements, with animation (bug #7141)", function() { ...@@ -910,7 +919,7 @@ test("hide hidden elements, with animation (bug #7141)", function() {
var div = jQuery("<div style='display:none'></div>").appendTo("#main"); var div = jQuery("<div style='display:none'></div>").appendTo("#main");
equals( div.css("display"), "none", "Element is hidden by default" ); equals( div.css("display"), "none", "Element is hidden by default" );
div.hide(1, function () { div.hide(1, function () {
ok( !div.data("olddisplay"), "olddisplay is undefined after hiding an already-hidden element" ); ok( !jQuery._data(div, "olddisplay"), "olddisplay is undefined after hiding an already-hidden element" );
div.show(1, function () { div.show(1, function () {
equals( div.css("display"), "block", "Show a double-hidden element" ); equals( div.css("display"), "block", "Show a double-hidden element" );
start(); start();
......
module("event"); module("event", { teardown: moduleTeardown });
test("null or undefined handler", function() { test("null or undefined handler", function() {
expect(2); expect(2);
...@@ -28,7 +28,7 @@ test("bind(), with data", function() { ...@@ -28,7 +28,7 @@ test("bind(), with data", function() {
}; };
jQuery("#firstp").bind("click", {foo: "bar"}, handler).click().unbind("click", handler); jQuery("#firstp").bind("click", {foo: "bar"}, handler).click().unbind("click", handler);
ok( !jQuery.data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." ); ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
}); });
test("click(), with data", function() { test("click(), with data", function() {
...@@ -39,7 +39,7 @@ test("click(), with data", function() { ...@@ -39,7 +39,7 @@ test("click(), with data", function() {
}; };
jQuery("#firstp").click({foo: "bar"}, handler).click().unbind("click", handler); jQuery("#firstp").click({foo: "bar"}, handler).click().unbind("click", handler);
ok( !jQuery.data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." ); ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
}); });
test("bind(), with data, trigger with data", function() { test("bind(), with data, trigger with data", function() {
...@@ -80,6 +80,9 @@ test("bind(), multiple events at once and namespaces", function() { ...@@ -80,6 +80,9 @@ test("bind(), multiple events at once and namespaces", function() {
cur = "focusin"; cur = "focusin";
div.trigger("focusin.a"); div.trigger("focusin.a");
// manually clean up detached elements
div.remove();
div = jQuery("<div/>").bind("click mouseover", obj, function(e) { div = jQuery("<div/>").bind("click mouseover", obj, function(e) {
equals( e.type, cur, "Verify right multi event was fired." ); equals( e.type, cur, "Verify right multi event was fired." );
equals( e.data, obj, "Make sure the data came in correctly." ); equals( e.data, obj, "Make sure the data came in correctly." );
...@@ -91,6 +94,9 @@ test("bind(), multiple events at once and namespaces", function() { ...@@ -91,6 +94,9 @@ test("bind(), multiple events at once and namespaces", function() {
cur = "mouseover"; cur = "mouseover";
div.trigger("mouseover"); div.trigger("mouseover");
// manually clean up detached elements
div.remove();
div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) { div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) {
equals( e.type, cur, "Verify right multi event was fired." ); equals( e.type, cur, "Verify right multi event was fired." );
}); });
...@@ -100,6 +106,9 @@ test("bind(), multiple events at once and namespaces", function() { ...@@ -100,6 +106,9 @@ test("bind(), multiple events at once and namespaces", function() {
cur = "focusout"; cur = "focusout";
div.trigger("focusout.b"); div.trigger("focusout.b");
// manually clean up detached elements
div.remove();
}); });
test("bind(), namespace with special add", function() { test("bind(), namespace with special add", function() {
...@@ -513,7 +522,7 @@ test("bind(), with different this object", function() { ...@@ -513,7 +522,7 @@ test("bind(), with different this object", function() {
.bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1) .bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1)
.bind("click", data, jQuery.proxy(handler2, thisObject)).click().unbind("click", handler2); .bind("click", data, jQuery.proxy(handler2, thisObject)).click().unbind("click", handler2);
ok( !jQuery.data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data." ); ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data." );
}); });
test("bind(name, false), unbind(name, false)", function() { test("bind(name, false), unbind(name, false)", function() {
...@@ -533,6 +542,9 @@ test("bind(name, false), unbind(name, false)", function() { ...@@ -533,6 +542,9 @@ test("bind(name, false), unbind(name, false)", function() {
jQuery("#ap").unbind("click", false); jQuery("#ap").unbind("click", false);
jQuery("#ap").trigger("click"); jQuery("#ap").trigger("click");
equals( main, 1, "Verify that the trigger happened correctly." ); equals( main, 1, "Verify that the trigger happened correctly." );
// manually clean up events from elements outside the fixture
jQuery("#main").unbind("click");
}); });
test("bind()/trigger()/unbind() on plain object", function() { test("bind()/trigger()/unbind() on plain object", function() {
...@@ -555,7 +567,7 @@ test("bind()/trigger()/unbind() on plain object", function() { ...@@ -555,7 +567,7 @@ test("bind()/trigger()/unbind() on plain object", function() {
} }
}); });
var events = jQuery(obj).data("__events__"); var events = jQuery._data(obj, "events");
ok( events, "Object has events bound." ); ok( events, "Object has events bound." );
equals( obj.events, undefined, "Events object on plain objects is not events" ); equals( obj.events, undefined, "Events object on plain objects is not events" );
equals( typeof events, "function", "'events' expando is a function on plain objects." ); equals( typeof events, "function", "'events' expando is a function on plain objects." );
...@@ -575,7 +587,9 @@ test("bind()/trigger()/unbind() on plain object", function() { ...@@ -575,7 +587,9 @@ test("bind()/trigger()/unbind() on plain object", function() {
// Make sure it doesn't complain when no events are found // Make sure it doesn't complain when no events are found
jQuery(obj).unbind("test"); jQuery(obj).unbind("test");
equals( obj.__events__, undefined, "Make sure events object is removed" ); equals( obj && obj[ jQuery.expando ] &&
obj[ jQuery.expando ][ jQuery.expando ] &&
obj[ jQuery.expando ][ jQuery.expando ].events, undefined, "Make sure events object is removed" );
}); });
test("unbind(type)", function() { test("unbind(type)", function() {
...@@ -669,13 +683,18 @@ test("hover()", function() { ...@@ -669,13 +683,18 @@ test("hover()", function() {
test("trigger() shortcuts", function() { test("trigger() shortcuts", function() {
expect(6); expect(6);
jQuery('<li><a href="#">Change location</a></li>').prependTo('#firstUL').find('a').bind('click', function() {
var elem = jQuery('<li><a href="#">Change location</a></li>').prependTo('#firstUL');
elem.find('a').bind('click', function() {
var close = jQuery('spanx', this); // same with jQuery(this).find('span'); var close = jQuery('spanx', this); // same with jQuery(this).find('span');
equals( close.length, 0, "Context element does not exist, length must be zero" ); equals( close.length, 0, "Context element does not exist, length must be zero" );
ok( !close[0], "Context element does not exist, direct access to element must return undefined" ); ok( !close[0], "Context element does not exist, direct access to element must return undefined" );
return false; return false;
}).click(); }).click();
// manually clean up detached elements
elem.remove();
jQuery("#check1").click(function() { jQuery("#check1").click(function() {
ok( true, "click event handler for checkbox gets fired twice, see #815" ); ok( true, "click event handler for checkbox gets fired twice, see #815" );
}).click(); }).click();
...@@ -694,9 +713,12 @@ test("trigger() shortcuts", function() { ...@@ -694,9 +713,12 @@ test("trigger() shortcuts", function() {
jQuery('#simon1').click(); jQuery('#simon1').click();
equals( clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also" ); equals( clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also" );
jQuery('<img />').load(function(){ elem = jQuery('<img />').load(function(){
ok( true, "Trigger the load event, using the shortcut .load() (#2819)"); ok( true, "Trigger the load event, using the shortcut .load() (#2819)");
}).load(); }).load();
// manually clean up detached elements
elem.remove();
}); });
test("trigger() bubbling", function() { test("trigger() bubbling", function() {
...@@ -731,6 +753,10 @@ test("trigger() bubbling", function() { ...@@ -731,6 +753,10 @@ test("trigger() bubbling", function() {
equals( body, 2, "ap bubble" ); equals( body, 2, "ap bubble" );
equals( main, 1, "ap bubble" ); equals( main, 1, "ap bubble" );
equals( ap, 1, "ap bubble" ); equals( ap, 1, "ap bubble" );
// manually clean up events from elements outside the fixture
jQuery(document).unbind("click");
jQuery("html, body, #main").unbind("click");
}); });
test("trigger(type, [data], [fn])", function() { test("trigger(type, [data], [fn])", function() {
...@@ -774,7 +800,7 @@ test("trigger(type, [data], [fn])", function() { ...@@ -774,7 +800,7 @@ test("trigger(type, [data], [fn])", function() {
pass = true; pass = true;
try { try {
jQuery('table:first').bind('test:test', function(){}).trigger('test:test'); jQuery('#main table:first').bind('test:test', function(){}).trigger('test:test');
} catch (e) { } catch (e) {
pass = false; pass = false;
} }
...@@ -955,9 +981,12 @@ test("toggle(Function, Function, ...)", function() { ...@@ -955,9 +981,12 @@ test("toggle(Function, Function, ...)", function() {
equals( turn, 2, "Trying toggle with 3 functions, attempt 5 yields 2"); equals( turn, 2, "Trying toggle with 3 functions, attempt 5 yields 2");
$div.unbind('click',fns[0]); $div.unbind('click',fns[0]);
var data = jQuery.data( $div[0], 'events' ); var data = jQuery._data( $div[0], 'events' );
ok( !data, "Unbinding one function from toggle unbinds them all"); ok( !data, "Unbinding one function from toggle unbinds them all");
// manually clean up detached elements
$div.remove();
// Test Multi-Toggles // Test Multi-Toggles
var a = [], b = []; var a = [], b = [];
$div = jQuery("<div/>"); $div = jQuery("<div/>");
...@@ -973,6 +1002,9 @@ test("toggle(Function, Function, ...)", function() { ...@@ -973,6 +1002,9 @@ test("toggle(Function, Function, ...)", function() {
$div.click(); $div.click();
same( a, [1,2,1], "Check that a click worked with a second toggle, second click." ); same( a, [1,2,1], "Check that a click worked with a second toggle, second click." );
same( b, [1,2], "Check that a click worked with a second toggle, second click." ); same( b, [1,2], "Check that a click worked with a second toggle, second click." );
// manually clean up detached elements
$div.remove();
}); });
test(".live()/.die()", function() { test(".live()/.die()", function() {
...@@ -1073,7 +1105,7 @@ test(".live()/.die()", function() { ...@@ -1073,7 +1105,7 @@ test(".live()/.die()", function() {
equals( clicked, 2, "live with a context" ); equals( clicked, 2, "live with a context" );
// Make sure the event is actually stored on the context // Make sure the event is actually stored on the context
ok( jQuery.data(container, "events").live, "live with a context" ); ok( jQuery._data(container, "events").live, "live with a context" );
// Test unbinding with a different context // Test unbinding with a different context
jQuery("#foo", container).die("click"); jQuery("#foo", container).die("click");
...@@ -1283,6 +1315,9 @@ test("live with multiple events", function(){ ...@@ -1283,6 +1315,9 @@ test("live with multiple events", function(){
div.trigger("submit"); div.trigger("submit");
equals( count, 2, "Make sure both the click and submit were triggered." ); equals( count, 2, "Make sure both the click and submit were triggered." );
// manually clean up events from elements outside the fixture
div.die();
}); });
test("live with namespaces", function(){ test("live with namespaces", function(){
...@@ -1586,7 +1621,7 @@ test(".delegate()/.undelegate()", function() { ...@@ -1586,7 +1621,7 @@ test(".delegate()/.undelegate()", function() {
equals( clicked, 2, "delegate with a context" ); equals( clicked, 2, "delegate with a context" );
// Make sure the event is actually stored on the context // Make sure the event is actually stored on the context
ok( jQuery.data(container, "events").live, "delegate with a context" ); ok( jQuery._data(container, "events").live, "delegate with a context" );
// Test unbinding with a different context // Test unbinding with a different context
jQuery("#main").undelegate("#foo", "click"); jQuery("#main").undelegate("#foo", "click");
...@@ -1915,7 +1950,7 @@ test("window resize", function() { ...@@ -1915,7 +1950,7 @@ test("window resize", function() {
ok( true, "Resize event fired." ); ok( true, "Resize event fired." );
}).resize().unbind("resize"); }).resize().unbind("resize");
ok( !jQuery(window).data("__events__"), "Make sure all the events are gone." ); ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." );
}); });
test("focusin bubbles", function() { test("focusin bubbles", function() {
......
module("manipulation"); module("manipulation", { teardown: moduleTeardown });
// Ensure that an extended Array prototype doesn't break jQuery // Ensure that an extended Array prototype doesn't break jQuery
Array.prototype.arrayProtoFn = function(arg) { throw("arrayProtoFn should not be called"); }; Array.prototype.arrayProtoFn = function(arg) { throw("arrayProtoFn should not be called"); };
...@@ -115,12 +115,19 @@ var testWrap = function(val) { ...@@ -115,12 +115,19 @@ var testWrap = function(val) {
// Wrap an element with a jQuery set and event // Wrap an element with a jQuery set and event
result = jQuery("<div></div>").click(function(){ result = jQuery("<div></div>").click(function(){
ok(true, "Event triggered."); ok(true, "Event triggered.");
// Remove handlers on detached elements
result.unbind();
jQuery(this).unbind();
}); });
j = jQuery("<span/>").wrap(result); j = jQuery("<span/>").wrap(result);
equals( j[0].parentNode.nodeName.toLowerCase(), "div", "Wrapping works." ); equals( j[0].parentNode.nodeName.toLowerCase(), "div", "Wrapping works." );
j.parent().trigger("click"); j.parent().trigger("click");
// clean up attached elements
QUnit.reset();
} }
test("wrap(String|Element)", function() { test("wrap(String|Element)", function() {
...@@ -408,8 +415,12 @@ test("append the same fragment with events (Bug #6997, 5566)", function () { ...@@ -408,8 +415,12 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
ok(true, "Event exists on original after being unbound on clone"); ok(true, "Event exists on original after being unbound on clone");
jQuery(this).unbind('click'); jQuery(this).unbind('click');
}); });
element.clone(true).unbind('click')[0].fireEvent('onclick'); var clone = element.clone(true).unbind('click');
clone[0].fireEvent('onclick');
element[0].fireEvent('onclick'); element[0].fireEvent('onclick');
// manually clean up detached elements
clone.remove();
} }
element = jQuery("<a class='test6997'></a>").click(function () { element = jQuery("<a class='test6997'></a>").click(function () {
...@@ -886,20 +897,36 @@ test("clone()", function() { ...@@ -886,20 +897,36 @@ test("clone()", function() {
ok( true, "Bound event still exists." ); ok( true, "Bound event still exists." );
}); });
div = div.clone(true).clone(true); clone = div.clone(true);
// manually clean up detached elements
div.remove();
div = clone.clone(true);
// manually clean up detached elements
clone.remove();
equals( div.length, 1, "One element cloned" ); equals( div.length, 1, "One element cloned" );
equals( div[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" ); equals( div[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div.trigger("click"); div.trigger("click");
// manually clean up detached elements
div.remove();
div = jQuery("<div/>").append([ document.createElement("table"), document.createElement("table") ]); div = jQuery("<div/>").append([ document.createElement("table"), document.createElement("table") ]);
div.find("table").click(function(){ div.find("table").click(function(){
ok( true, "Bound event still exists." ); ok( true, "Bound event still exists." );
}); });
div = div.clone(true); clone = div.clone(true);
equals( div.length, 1, "One element cloned" ); equals( clone.length, 1, "One element cloned" );
equals( div[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" ); equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div.find("table:last").trigger("click"); clone.find("table:last").trigger("click");
// manually clean up detached elements
div.remove();
clone.remove();
// this is technically an invalid object, but because of the special // this is technically an invalid object, but because of the special
// classid instantiation it is the only kind that IE has trouble with, // classid instantiation it is the only kind that IE has trouble with,
...@@ -920,12 +947,16 @@ test("clone()", function() { ...@@ -920,12 +947,16 @@ test("clone()", function() {
equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" ); equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div = jQuery("<div/>").data({ a: true }); div = jQuery("<div/>").data({ a: true });
var div2 = div.clone(true); clone = div.clone(true);
equals( div2.data("a"), true, "Data cloned." ); equals( clone.data("a"), true, "Data cloned." );
div2.data("a", false); clone.data("a", false);
equals( div2.data("a"), false, "Ensure cloned element data object was correctly modified" ); equals( clone.data("a"), false, "Ensure cloned element data object was correctly modified" );
equals( div.data("a"), true, "Ensure cloned element data object is copied, not referenced" ); equals( div.data("a"), true, "Ensure cloned element data object is copied, not referenced" );
// manually clean up detached elements
div.remove();
clone.remove();
var form = document.createElement("form"); var form = document.createElement("form");
form.action = "/test/"; form.action = "/test/";
var div = document.createElement("div"); var div = document.createElement("div");
...@@ -1155,15 +1186,21 @@ var testRemove = function(method) { ...@@ -1155,15 +1186,21 @@ var testRemove = function(method) {
jQuery("#nonnodes").contents()[method](); jQuery("#nonnodes").contents()[method]();
equals( jQuery("#nonnodes").contents().length, 0, "Check node,textnode,comment remove works" ); equals( jQuery("#nonnodes").contents().length, 0, "Check node,textnode,comment remove works" );
// manually clean up detached elements
if (method === "detach") {
first.remove();
}
QUnit.reset(); QUnit.reset();
var count = 0; var count = 0;
var first = jQuery("#ap").children(":first"); var first = jQuery("#ap").children(":first");
var cleanUp = first.click(function() { count++ })[method]().appendTo("body").click(); var cleanUp = first.click(function() { count++ })[method]().appendTo("#main").click();
equals( method == "remove" ? 0 : 1, count ); equals( method == "remove" ? 0 : 1, count );
cleanUp.detach(); // manually clean up detached elements
cleanUp.remove();
}; };
test("remove()", function() { test("remove()", function() {
......
module("offset"); module("offset", { teardown: moduleTeardown });
test("disconnected node", function() { test("disconnected node", function() {
expect(2); expect(2);
......
module("queue"); module("queue", { teardown: moduleTeardown });
test("queue() with other types",function() { test("queue() with other types",function() {
expect(9); expect(9);
......
module("selector"); module("selector", { teardown: moduleTeardown });
test("element", function() { test("element", function() {
expect(21); expect(21);
......
module("traversing"); module("traversing", { teardown: moduleTeardown });
test("find(String)", function() { test("find(String)", function() {
expect(5); expect(5);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment