fcleanup = function( nm ) {
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.
}
// 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
// banned noData elements
return;
}
- // Use a key less likely to result in collisions for plain JS objects.
- // Fixes bug #7150.
- var eventKey = elem.nodeType ? "events" : "__events__",
- events = elemData[ eventKey ],
+ var events = elemData[ eventKey ],
eventHandle = elemData.handle;
if ( typeof events === "function" ) {
}
var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
- eventKey = elem.nodeType ? "events" : "__events__",
- elemData = jQuery.data( elem ),
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
events = elemData && elemData[ eventKey ];
if ( !elemData || !events ) {
delete elemData.handle;
if ( typeof elemData === "function" ) {
- jQuery.removeData( elem, eventKey );
+ jQuery.removeData( elem, eventKey, true );
} else if ( jQuery.isEmptyObject( elemData ) ) {
- jQuery.removeData( elem );
+ jQuery.removeData( elem, undefined, true );
}
}
},
// Only trigger if we've ever bound an event for it
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() {
- if ( this.events && this.events[type] ) {
- jQuery.event.trigger( event, data, this.handle.elem );
+ // internalKey variable is just used to make it easier to find
+ // 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 );
}
});
}
// Trigger the event, it is assumed that "handle" is a function
var handle = elem.nodeType ?
- jQuery.data( elem, "handle" ) :
- (jQuery.data( elem, "__events__" ) || {}).handle;
+ jQuery._data( elem, "handle" ) :
+ (jQuery._data( elem, eventKey ) || {}).handle;
if ( handle ) {
handle.apply( elem, data );
event.namespace = event.namespace || namespace_sort.join(".");
- events = jQuery.data(this, this.nodeType ? "events" : "__events__");
+ events = jQuery._data(this, eventKey);
if ( typeof events === "function" ) {
events = events.events;
// Events bubbling up the document may have been marked as prevented
// by a handler lower down the tree; reflect the correct value.
- this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
+ this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
// Event type
return;
}
- data = jQuery.data( elem, "_change_data" );
+ data = jQuery._data( elem, "_change_data" );
val = getVal(elem);
// the current data will be also retrieved by beforeactivate
if ( e.type !== "focusout" || elem.type !== "radio" ) {
- jQuery.data( elem, "_change_data", val );
+ jQuery._data( elem, "_change_data", val );
}
if ( data === undefined || val === data ) {
// information
beforeactivate: function( e ) {
var elem = e.target;
- jQuery.data( elem, "_change_data", getVal(elem) );
+ jQuery._data( elem, "_change_data", getVal(elem) );
}
},
return this.click( jQuery.proxy( fn, function( event ) {
// Figure out which function to execute
- var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
- jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
// Make sure that clicks stop
event.preventDefault();
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
elems = [],
selectors = [],
- events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
+ events = jQuery._data( this, eventKey );
if ( typeof events === "function" ) {
events = events.events;
table ?
root(this[i], first) :
this[i],
- i > 0 || results.cacheable || this.length > 1 ?
+ i > 0 || results.cacheable || (this.length > 1 && i > 0) ?
jQuery(fragment).clone(true)[0] :
fragment
);
throw "Cloned data mismatch";
}
- var oldData = jQuery.data( orig[nodeIndex] ),
- curData = jQuery.data( this, oldData ),
- events = oldData && oldData.events;
+ var internalKey = jQuery.expando,
+ oldData = jQuery.data( orig[nodeIndex] ),
+ curData = jQuery.data( this, oldData );
- if ( events ) {
- delete curData.handle;
- curData.events = {};
+ // Switch to use the internal data object, if it exists, for the next
+ // stage of data copying
+ if ( (oldData = oldData[ internalKey ]) ) {
+ var events = oldData.events;
+ curData = curData[ internalKey ] = jQuery.extend({}, oldData);
- 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 );
+ if ( events ) {
+ delete curData.handle;
+ 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 );
+ }
}
}
}
if ( nodeName === "object" ) {
dest.outerHTML = src.outerHTML;
- // IE6-8 fails to persist the checked state of a cloned checkbox
- // or radio button
- } else if ( nodeName === "input" && src.checked ) {
- dest.defaultChecked = dest.checked = src.checked;
+ } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+ // 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
+ if ( src.checked ) {
+ 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.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
}
// Event data gets referenced instead of copied if the expando
},
cleanData: function( elems ) {
- var data, id, cache = jQuery.cache,
- special = jQuery.event.special,
+ var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
deleteExpando = jQuery.support.deleteExpando;
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
id = elem[ jQuery.expando ];
if ( id ) {
- data = cache[ id ];
+ data = cache[ id ] && cache[ id ][ internalKey ];
if ( data && data.events ) {
for ( var 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 );
}
}
+
+ // Null the DOM reference to avoid IE6/7/8 leak (#7054)
+ if ( data.handle ) {
+ data.handle.elem = null;
+ }
}
if ( deleteExpando ) {
- module("ajax");
+ module("ajax", { teardown: moduleTeardown });
// Safari 3 randomly crashes when running these tests,
// but only in the full suite - you can run just the Ajax
start();
}
}
- })
+ });
});
});
+test(".ajax() - Accept header" , function() {
+
+ expect( 1 );
+
+ stop();
+
+ jQuery.ajax(url("data/headers.php?keys=accept"), {
+ headers: {
+ Accept: "very wrong accept value"
+ },
+ beforeSend: function( xhr ) {
+ xhr.setRequestHeader( "Accept", "*/*" );
+ },
+ success: function( data ) {
+ strictEqual( data , "accept: */*\n" , "Test Accept header is set to last value provided" );
+ start();
+ },
+ error: function(){ ok(false, "error"); }
+ });
+
+});
+
test(".ajax() - contentType" , function() {
expect( 2 );
});
});
+test("load(String, Function) - dataFilter in ajaxSettings", function() {
+ expect(2);
+ stop();
+ jQuery.ajaxSetup({ dataFilter: function() { return "Hello World"; } });
+ var div = jQuery("<div/>").load(url("data/name.html"), function(responseText) {
+ strictEqual( div.html(), "Hello World" , "Test div was filled with filtered data" );
+ strictEqual( responseText, "Hello World" , "Test callback receives filtered data" );
+ jQuery.ajaxSetup({ dataFilter: 0 });
+ start();
+ });
+});
+
test("load(String, Object, Function)", function() {
expect(2);
stop();
});
});
-test("jQuery.ajax() - JSONP, Local", function() {
- expect(10);
-
- var count = 0;
- function plus(){ if ( ++count == 9 ) start(); }
-
- stop();
-
- jQuery.ajax({
- url: "data/jsonp.php",
- dataType: "jsonp",
- success: function(data){
- ok( data.data, "JSON results returned (GET, no callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, no callback)" );
- plus();
- }
- });
+jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label ) {
- jQuery.ajax({
- url: "data/jsonp.php?callback=?",
- dataType: "jsonp",
- success: function(data){
- ok( data.data, "JSON results returned (GET, url callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, url callback)" );
- plus();
- }
- });
+ test("jQuery.ajax() - JSONP, " + label, function() {
+ expect(17);
- jQuery.ajax({
- url: "data/jsonp.php",
- dataType: "jsonp",
- data: "callback=?",
- success: function(data){
- ok( data.data, "JSON results returned (GET, data callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, data callback)" );
- plus();
- }
- });
+ var count = 0;
+ function plus(){ if ( ++count == 17 ) start(); }
- jQuery.ajax({
- url: "data/jsonp.php",
- dataType: "jsonp",
- data: {
- callback: "?"
- },
- success: function(data){
- ok( data.data, "JSON results returned (GET, processed data callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, processed data callback)" );
- plus();
- }
- });
+ stop();
- jQuery.ajax({
- url: "data/jsonp.php",
- dataType: "jsonp",
- jsonp: "callback",
- success: function(data){
- ok( data.data, "JSON results returned (GET, data obj callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, data obj callback)" );
- plus();
- }
- });
+ jQuery.ajax({
+ url: "data/jsonp.php",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, no callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, no callback)" );
+ plus();
+ }
+ });
- jQuery.ajax({
- url: "data/jsonp.php",
- dataType: "jsonp",
- jsonpCallback: "jsonpResults",
- success: function(data){
- ok( data.data, "JSON results returned (GET, custom callback name)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, custom callback name)" );
- plus();
- }
- });
+ jQuery.ajax({
+ url: "data/jsonp.php?callback=?",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, url callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, url callback)" );
+ plus();
+ }
+ });
- jQuery.ajax({
- type: "POST",
- url: "data/jsonp.php",
- dataType: "jsonp",
- success: function(data){
- ok( data.data, "JSON results returned (POST, no callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, data obj callback)" );
- plus();
- }
- });
+ jQuery.ajax({
+ url: "data/jsonp.php",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ data: "callback=?",
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, data callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, data callback)" );
+ plus();
+ }
+ });
- jQuery.ajax({
- type: "POST",
- url: "data/jsonp.php",
- data: "callback=?",
- dataType: "jsonp",
- success: function(data){
- ok( data.data, "JSON results returned (POST, data callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (POST, data callback)" );
- plus();
- }
- });
+ jQuery.ajax({
+ url: "data/jsonp.php?callback=??",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, url context-free callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, url context-free callback)" );
+ plus();
+ }
+ });
- jQuery.ajax({
- type: "POST",
- url: "data/jsonp.php",
- jsonp: "callback",
- dataType: "jsonp",
- success: function(data){
- ok( data.data, "JSON results returned (POST, data obj callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (POST, data obj callback)" );
- plus();
- }
- });
+ jQuery.ajax({
+ url: "data/jsonp.php",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ data: "callback=??",
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, data context-free callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, data context-free callback)" );
+ plus();
+ }
+ });
- //#7578
- jQuery.ajax({
- url: "data/jsonp.php",
- dataType: "jsonp",
- beforeSend: function(){
- strictEqual( this.cache, false, "cache must be false on JSON request" );
- plus();
- return false;
- }
- });
-});
+ jQuery.ajax({
+ url: "data/jsonp.php/??",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, REST-like)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, REST-like)" );
+ plus();
+ }
+ });
-test("jQuery.ajax() - JSONP - Custom JSONP Callback", function() {
- expect(1);
- stop();
+ jQuery.ajax({
+ url: "data/jsonp.php/???json=1",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ success: function(data){
+ strictEqual( jQuery.type(data), "array", "JSON results returned (GET, REST-like with param)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, REST-like with param)" );
+ plus();
+ }
+ });
- window.jsonpResults = function(data) {
- ok( data.data, "JSON results returned (GET, custom callback function)" );
- window.jsonpResults = undefined;
- start();
- };
+ jQuery.ajax({
+ url: "data/jsonp.php",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ data: {
+ callback: "?"
+ },
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, processed data callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, processed data callback)" );
+ plus();
+ }
+ });
- jQuery.ajax({
- url: "data/jsonp.php",
- dataType: "jsonp",
- jsonpCallback: "jsonpResults"
- });
-});
+ jQuery.ajax({
+ url: "data/jsonp.php",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ jsonp: "callback",
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, data obj callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, data obj callback)" );
+ plus();
+ }
+ });
-test("jQuery.ajax() - JSONP, Remote", function() {
- expect(4);
+ window.jsonpResults = function(data) {
+ ok( data.data, "JSON results returned (GET, custom callback function)" );
+ window.jsonpResults = undefined;
+ plus();
+ };
- var count = 0;
- function plus(){ if ( ++count == 4 ) start(); }
+ jQuery.ajax({
+ url: "data/jsonp.php",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ jsonpCallback: "jsonpResults",
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, custom callback name)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, custom callback name)" );
+ plus();
+ }
+ });
- var base = window.location.href.replace(/[^\/]*$/, "");
+ jQuery.ajax({
+ type: "POST",
+ url: "data/jsonp.php",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ success: function(data){
+ ok( data.data, "JSON results returned (POST, no callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, data obj callback)" );
+ plus();
+ }
+ });
- stop();
+ jQuery.ajax({
+ type: "POST",
+ url: "data/jsonp.php",
+ data: "callback=?",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ success: function(data){
+ ok( data.data, "JSON results returned (POST, data callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (POST, data callback)" );
+ plus();
+ }
+ });
- jQuery.ajax({
- url: base + "data/jsonp.php",
- dataType: "jsonp",
- success: function(data){
- ok( data.data, "JSON results returned (GET, no callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, no callback)" );
- plus();
- }
- });
+ jQuery.ajax({
+ type: "POST",
+ url: "data/jsonp.php",
+ jsonp: "callback",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ success: function(data){
+ ok( data.data, "JSON results returned (POST, data obj callback)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (POST, data obj callback)" );
+ plus();
+ }
+ });
- jQuery.ajax({
- url: base + "data/jsonp.php?callback=?",
- dataType: "jsonp",
- success: function(data){
- ok( data.data, "JSON results returned (GET, url callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, url callback)" );
- plus();
- }
- });
+ //#7578
+ jQuery.ajax({
+ url: "data/jsonp.php",
+ dataType: "jsonp",
+ crossDomain: crossDomain,
+ beforeSend: function(){
+ strictEqual( this.cache, false, "cache must be false on JSON request" );
+ plus();
+ return false;
+ }
+ });
- jQuery.ajax({
- url: base + "data/jsonp.php",
- dataType: "jsonp",
- data: "callback=?",
- success: function(data){
- ok( data.data, "JSON results returned (GET, data callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, data callback)" );
- plus();
- }
- });
+ jQuery.ajax({
+ url: "data/jsonp.php?callback=XXX",
+ dataType: "jsonp",
+ jsonp: false,
+ jsonpCallback: "XXX",
+ crossDomain: crossDomain,
+ beforeSend: function() {
+ ok( /^data\/jsonp.php\?callback=XXX&_=\d+$/.test( this.url ) ,
+ "The URL wasn't messed with (GET, custom callback name with no url manipulation)" );
+ plus();
+ },
+ success: function(data){
+ ok( data.data, "JSON results returned (GET, custom callback name with no url manipulation)" );
+ plus();
+ },
+ error: function(data){
+ ok( false, "Ajax error JSON (GET, custom callback name with no url manipulation)" );
+ plus();
+ }
+ });
- jQuery.ajax({
- url: base + "data/jsonp.php",
- dataType: "jsonp",
- jsonp: "callback",
- success: function(data){
- ok( data.data, "JSON results returned (GET, data obj callback)" );
- plus();
- },
- error: function(data){
- ok( false, "Ajax error JSON (GET, data obj callback)" );
- plus();
- }
});
});
var i = 2;
- if ( jQuery.ajax({
+ jQuery.ajax({
url: 'http://somewebsitethatdoesnotexist-67864863574657654.com',
success: function(){ ok( false , "success" ); },
error: function(xhr,_,e){ ok( true , "file not found: " + xhr.status + " => " + e ); },
complete: function() { if ( ! --i ) start(); }
- }) === false ) {
- ok( true , "no transport" );
- if ( ! --i ) start();
- }
+ });
- if ( jQuery.ajax({
+ jQuery.ajax({
url: 'http://www.google.com',
success: function(){ ok( false , "success" ); },
error: function(xhr,_,e){ ok( true , "access denied: " + xhr.status + " => " + e ); },
complete: function() { if ( ! --i ) start(); }
- }) === false ) {
- ok( true , "no transport" );
- if ( ! --i ) start();
- }
+ });
});
ok( success, "document.location did not generate exception" );
});
+test( "jQuery.ajax - statusCode" , function() {
+
+ var count = 10;
+
+ expect( 16 );
+ stop();
+
+ function countComplete() {
+ if ( ! --count ) {
+ start();
+ }
+ }
+
+ function createStatusCodes( name , isSuccess ) {
+ name = "Test " + name + " " + ( isSuccess ? "success" : "error" );
+ return {
+ 200: function() {
+ ok( isSuccess , name );
+ },
+ 404: function() {
+ ok( ! isSuccess , name );
+ }
+ };
+ }
+
+ jQuery.each( {
+ "data/name.html": true,
+ "data/someFileThatDoesNotExist.html": false
+ } , function( uri , isSuccess ) {
+
+ jQuery.ajax( url( uri ) , {
+ statusCode: createStatusCodes( "in options" , isSuccess ),
+ complete: countComplete
+ });
+
+ jQuery.ajax( url( uri ) , {
+ complete: countComplete
+ }).statusCode( createStatusCodes( "immediately with method" , isSuccess ) );
+
+ jQuery.ajax( url( uri ) , {
+ complete: function(jXHR) {
+ jXHR.statusCode( createStatusCodes( "on complete" , isSuccess ) );
+ countComplete();
+ }
+ });
+
+ jQuery.ajax( url( uri ) , {
+ complete: function(jXHR) {
+ setTimeout( function() {
+ jXHR.statusCode( createStatusCodes( "very late binding" , isSuccess ) );
+ countComplete();
+ } , 100 );
+ }
+ });
+
+ jQuery.ajax( url( uri ) , {
+ statusCode: createStatusCodes( "all (options)" , isSuccess ),
+ complete: function(jXHR) {
+ jXHR.statusCode( createStatusCodes( "all (on complete)" , isSuccess ) );
+ setTimeout( function() {
+ jXHR.statusCode( createStatusCodes( "all (very late binding)" , isSuccess ) );
+ countComplete();
+ } , 100 );
+ }
+ }).statusCode( createStatusCodes( "all (immediately with method)" , isSuccess ) );
+
+ });
+
+});
+
}
//}
- module("core");
+ module("core", { teardown: moduleTeardown });
test("Basic requirements", function() {
expect(7);
});
test("jQuery()", function() {
- expect(23);
+ expect(24);
// Basic constructor's behavior
equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" );
equals( jQuery("").length, 0, "jQuery('') === jQuery([])" );
- var obj = jQuery("div")
+ var obj = jQuery("div");
equals( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" );
// can actually yield more than one, when iframes are included, the window is an array as well
exec = true;
elem.click();
+ // manually clean up detached elements
+ elem.remove();
++
+ for ( var i = 0; i < 3; ++i ) {
+ elem = jQuery("<input type='text' value='TEST' />");
+ }
+ 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("jQuery.Deferred()", function() {
- expect( 4 );
+ expect( 10 );
jQuery.Deferred( function( defer ) {
strictEqual( this , defer , "Defer passed as this & first argument" );
}, function() {
ok( true , "Error on reject" );
});
+
+ ( new jQuery.Deferred( function( defer ) {
+ strictEqual( this , defer , "Defer passed as this & first argument (new)" );
+ this.resolve( "done" );
+ }) ).then( function( value ) {
+ strictEqual( value , "done" , "Passed function executed (new)" );
+ });
+
+ ( new jQuery.Deferred() ).resolve().then( function() {
+ ok( true , "Success on resolve (new)" );
+ }, function() {
+ ok( false , "Error on resolve (new)" );
+ });
+
+ ( new jQuery.Deferred() ).reject().then( function() {
+ ok( false , "Success on reject (new)" );
+ }, function() {
+ ok( true , "Error on reject (new)" );
+ });
+
+ var tmp = jQuery.Deferred();
+
+ strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" );
+ strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" );
});
test("jQuery.when()", function() {
- expect( 21 );
+ expect( 23 );
// Some other objects
jQuery.each( {
} );
+ ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) {
+ strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" );
+ } ).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" );
+
var cache, i;
for( i = 1 ; i < 4 ; i++ ) {
});
}
});
+
+test("jQuery.when() - joined", function() {
+
+ expect(8);
+
+ jQuery.when( 1, 2, 3 ).done( function( a, b, c ) {
+ strictEqual( a , 1 , "Test first param is first resolved value - non-observables" );
+ strictEqual( b , 2 , "Test second param is second resolved value - non-observables" );
+ strictEqual( c , 3 , "Test third param is third resolved value - non-observables" );
+ }).fail( function() {
+ ok( false , "Test the created deferred was resolved - non-observables");
+ });
+
+ var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ),
+ errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" );
+
+ jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) {
+ strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" );
+ same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" );
+ strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" );
+ }).fail( function() {
+ ok( false , "Test the created deferred was resolved - resolved observable");
+ });
+
+ jQuery.when( 1 , errorDeferred , 3 ).done( function() {
+ ok( false , "Test the created deferred was rejected - rejected observable");
+ }).fail( function( error , errorParam ) {
+ strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" );
+ strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" );
+ });
+});
+
+test("jQuery.subclass", function(){
+ expect(378);
+
+ var Subclass = jQuery.subclass(),
+ SubclassSubclass = Subclass.subclass(),
+ jQueryDocument = jQuery(document),
+ selectors, contexts, methods, method, arg, description;
+
+ jQueryDocument.toString = function(){ return 'jQueryDocument'; };
+
+ Subclass.fn.subclassMethod = function(){};
+ SubclassSubclass.fn.subclassSubclassMethod = function(){};
+
+ selectors = [
+ 'body',
+ 'html, body',
+ '<div></div>'
+ ];
+
+ methods = [ // all methods that return a new jQuery instance
+ ['eq', 1],
+ ['add', document],
+ ['end'],
+ ['has'],
+ ['closest', 'div'],
+ ['filter', document],
+ ['find', 'div']
+ ];
+
+ contexts = [undefined, document, jQueryDocument];
+
+ jQuery.each(selectors, function(i, selector){
+
+ jQuery.each(methods, function(){
+ method = this[0];
+ arg = this[1];
+
+ jQuery.each(contexts, function(i, context){
+
+ description = '("'+selector+'", '+context+').'+method+'('+(arg||'')+')';
+
+ same(
+ jQuery(selector, context)[method](arg).subclassMethod, undefined,
+ 'jQuery'+description+' doesnt have Subclass methods'
+ );
+ same(
+ jQuery(selector, context)[method](arg).subclassSubclassMethod, undefined,
+ 'jQuery'+description+' doesnt have SubclassSubclass methods'
+ );
+ same(
+ Subclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
+ 'Subclass'+description+' has Subclass methods'
+ );
+ same(
+ Subclass(selector, context)[method](arg).subclassSubclassMethod, undefined,
+ 'Subclass'+description+' doesnt have SubclassSubclass methods'
+ );
+ same(
+ SubclassSubclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
+ 'SubclassSubclass'+description+' has Subclass methods'
+ );
+ same(
+ SubclassSubclass(selector, context)[method](arg).subclassSubclassMethod, SubclassSubclass.fn.subclassSubclassMethod,
+ 'SubclassSubclass'+description+' has SubclassSubclass methods'
+ );
+
+ });
+ });
+ });
+
+});
- module("css");
+ module("css", { teardown: moduleTeardown });
test("css(String|Hash)", function() {
expect(41);
jQuery('#table').css('display', 'none').html('<tr><td>cell</td><td>cell</td></tr>');
equals(jQuery('#table td:visible').length, 0, "hidden cell children not perceived as visible");
});
+
+test("internal ref to elem.runtimeStyle (bug #7608)", function () {
+ expect(1);
+
+ var result = true,
+ val = 10;
+
+ jQuery('<div id="bug7608" style="width:200px;border:solid 1px red;">' +
+ '<div id="test" style="width:0%; background:#000;"> </div></div>').appendTo("#main");
+
+ try {
+ // the bug is located within src/css.js
+ jQuery("#bug7608 #test").animate( { width: val }, 1000);
+
+ } catch (e) {
+ result = false;
+ }
+
+ ok( result, "elem.runtimeStyle does not throw exception" );
+
+ jQuery("#bug7608").remove();
+});
- module("event");
+ module("event", { teardown: moduleTeardown });
test("null or undefined handler", function() {
expect(2);
};
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() {
};
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() {
cur = "focusin";
div.trigger("focusin.a");
+ // manually clean up detached elements
+ div.remove();
+
div = jQuery("<div/>").bind("click mouseover", obj, function(e) {
equals( e.type, cur, "Verify right multi event was fired." );
equals( e.data, obj, "Make sure the data came in correctly." );
cur = "mouseover";
div.trigger("mouseover");
+ // manually clean up detached elements
+ div.remove();
+
div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) {
equals( e.type, cur, "Verify right multi event was fired." );
});
cur = "focusout";
div.trigger("focusout.b");
+
+ // manually clean up detached elements
+ div.remove();
});
test("bind(), namespace with special add", function() {
$p.undelegate( "click" );
});
-test("bind/delegate bubbling, isDefaultPrevented (Bug #7793)", function() {
+test("bind/delegate bubbling, isDefaultPrevented", function() {
expect(2);
var $anchor2 = jQuery( "#anchor2" ),
$main = jQuery( "#main" ),
fakeClick = function($jq) {
// Use a native click so we don't get jQuery simulated bubbling
if ( document.createEvent ) {
- var e = document.createEvent( "MouseEvents" );
- e.initEvent( "click", true, true );
+ var e = document.createEvent( 'MouseEvents' );
+ e.initEvent( "click", true, true );
$jq[0].dispatchEvent(e);
}
else if ( $jq[0].click ) {
e.preventDefault();
});
$main.delegate("#foo", "click", function(e) {
- equals( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
+ var orig = e.originalEvent;
+
+ if ( typeof(orig.defaultPrevented) === "boolean" || typeof(orig.returnValue) === "boolean" || orig.getPreventDefault ) {
+ equals( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
+
+ } else {
+ // Opera < 11 doesn't implement any interface we can use, so give it a pass
+ ok( true, "isDefaultPrevented not supported by this browser, test skipped" );
+ }
});
fakeClick( $anchor2 );
$anchor2.unbind( "click" );
.bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1)
.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() {
jQuery("#ap").unbind("click", false);
jQuery("#ap").trigger("click");
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() {
}
});
- var events = jQuery(obj).data("__events__");
+ var events = jQuery._data(obj, "events");
ok( events, "Object has events bound." );
equals( obj.events, undefined, "Events object on plain objects is not events" );
equals( typeof events, "function", "'events' expando is a function on plain objects." );
// Make sure it doesn't complain when no events are found
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("trigger() shortcuts", function() {
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');
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" );
return false;
}).click();
+ // manually clean up detached elements
+ elem.remove();
+
jQuery("#check1").click(function() {
ok( true, "click event handler for checkbox gets fired twice, see #815" );
}).click();
jQuery('#simon1').click();
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)");
}).load();
+
+ // manually clean up detached elements
+ elem.remove();
});
test("trigger() bubbling", function() {
equals( body, 2, "ap bubble" );
equals( main, 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() {
pass = true;
try {
- jQuery('table:first').bind('test:test', function(){}).trigger('test:test');
+ jQuery('#main table:first').bind('test:test', function(){}).trigger('test:test');
} catch (e) {
pass = false;
}
equals( turn, 2, "Trying toggle with 3 functions, attempt 5 yields 2");
$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");
+ // manually clean up detached elements
+ $div.remove();
+
// Test Multi-Toggles
var a = [], b = [];
$div = jQuery("<div/>");
$div.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." );
+
+ // manually clean up detached elements
+ $div.remove();
});
test(".live()/.die()", function() {
equals( clicked, 2, "live with a 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
jQuery("#foo", container).die("click");
div.trigger("submit");
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(){
equals( clicked, 2, "delegate with a 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
jQuery("#main").undelegate("#foo", "click");
ok( true, "Resize event fired." );
}).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() {
- module("manipulation");
+ module("manipulation", { teardown: moduleTeardown });
// Ensure that an extended Array prototype doesn't break jQuery
Array.prototype.arrayProtoFn = function(arg) { throw("arrayProtoFn should not be called"); };
// Wrap an element with a jQuery set and event
result = jQuery("<div></div>").click(function(){
ok(true, "Event triggered.");
+
+ // Remove handlers on detached elements
+ result.unbind();
+ jQuery(this).unbind();
});
j = jQuery("<span/>").wrap(result);
equals( j[0].parentNode.nodeName.toLowerCase(), "div", "Wrapping works." );
j.parent().trigger("click");
+
+ // clean up attached elements
+ QUnit.reset();
}
test("wrap(String|Element)", function() {
});
test("append the same fragment with events (Bug #6997, 5566)", function () {
- expect(4 + (document.fireEvent ? 1 : 0));
+ expect(2 + (document.fireEvent ? 1 : 0));
stop(1000);
var element;
ok(true, "Event exists on original after being unbound on clone");
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');
+
+ // manually clean up detached elements
+ clone.remove();
}
element = jQuery("<a class='test6997'></a>").click(function () {
jQuery("#listWithTabIndex li").before(element);
jQuery("#listWithTabIndex li.test6997").eq(1).click();
-
- element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
-
- equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
-
- element = jQuery("<input type='checkbox'>").attr('checked', 'checked');
-
- equals( element.clone().is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
});
test("appendTo(String|Element|Array<Element>|jQuery)", function() {
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[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div.trigger("click");
+ // manually clean up detached elements
+ div.remove();
+
div = jQuery("<div/>").append([ document.createElement("table"), document.createElement("table") ]);
div.find("table").click(function(){
ok( true, "Bound event still exists." );
});
- div = div.clone(true);
- equals( div.length, 1, "One element cloned" );
- equals( div[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
- div.find("table:last").trigger("click");
+ clone = div.clone(true);
+ equals( clone.length, 1, "One element cloned" );
+ equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
+ 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
// classid instantiation it is the only kind that IE has trouble with,
equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div = jQuery("<div/>").data({ a: true });
- var div2 = div.clone(true);
- equals( div2.data("a"), true, "Data cloned." );
- div2.data("a", false);
- equals( div2.data("a"), false, "Ensure cloned element data object was correctly modified" );
+ clone = div.clone(true);
+ equals( clone.data("a"), true, "Data cloned." );
+ clone.data("a", false);
+ 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" );
+ // manually clean up detached elements
+ div.remove();
+ clone.remove();
+
var form = document.createElement("form");
form.action = "/test/";
var div = document.createElement("div");
equal( jQuery("body").clone().children()[0].id, "qunit-header", "Make sure cloning body works" );
});
+test("clone(form element) (Bug #3879, #6655)", function() {
+ expect(6);
+ element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
+
+ equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
+
+ element = jQuery("<input type='checkbox' value='foo'>").attr('checked', 'checked');
+ clone = element.clone();
+
+ equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
+ equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" );
+ equals( clone[0].defaultChecked, !jQuery.support.noCloneEvent, "Checked input defaultChecked cloned correctly" );
+
+ element = jQuery("<input type='text' value='foo'>");
+ clone = element.clone();
+ equals( clone[0].defaultValue, "foo", "Text input defaultValue cloned correctly" );
+
+ element = jQuery("<textarea>foo</textarea>");
+ clone = element.clone();
+ equals( clone[0].defaultValue, "foo", "Textarea defaultValue cloned correctly" );
+});
+
if (!isLocal) {
test("clone() on XML nodes", function() {
expect(2);
jQuery("#nonnodes").contents()[method]();
equals( jQuery("#nonnodes").contents().length, 0, "Check node,textnode,comment remove works" );
+ // manually clean up detached elements
+ if (method === "detach") {
+ first.remove();
+ }
+
QUnit.reset();
var count = 0;
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 );
- cleanUp.detach();
+ // manually clean up detached elements
+ cleanUp.remove();
};
test("remove()", function() {