Index: src/ajax.js
===================================================================
--- src/ajax.js	(revision 6562)
+++ src/ajax.js	(working copy)
@@ -41,21 +41,20 @@
 			}
 		}
 
-		var self = this;
-
 		// Request the remote document
 		jQuery.ajax({
 			url: url,
 			type: type,
 			dataType: "html",
 			data: params,
+			context:this,
 			complete: function(res, status){
 				// If successful, inject the HTML into all the matched elements
 				if ( status === "success" || status === "notmodified" ) {
 					// See if a selector was specified
-					self.html( selector ?
+					this.html( selector ?
 						// Create a dummy div to hold the results
-						jQuery("<div/>")
+						jQuery("<div />")
 							// inject the contents of the document in, removing the scripts
 							// to avoid any 'Permission Denied' errors in IE
 							.append(res.responseText.replace(rscript, ""))
@@ -68,7 +67,7 @@
 				}
 
 				if ( callback ) {
-					self.each( callback, [res.responseText, status, res] );
+					this.each( callback, [res.responseText, status, res] );
 				}
 			}
 		});
@@ -193,8 +192,9 @@
 		// Extend the settings, but re-extend 's' so that it can be
 		// checked again later (in the test suite, specifically)
 		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
-
+		
 		var jsonp, status, data,
+			callbackContext = s.context || window,
 			type = s.type.toUpperCase();
 
 		// convert data if not already a string
@@ -352,7 +352,7 @@
 		} catch(e){}
 
 		// Allow custom headers/mimetypes and early abort
-		if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+		if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
 			// Handle the global AJAX counter
 			if ( s.global && ! --jQuery.active ) {
 				jQuery.event.trigger( "ajaxStop" );
@@ -364,7 +364,7 @@
 		}
 
 		if ( s.global ) {
-			jQuery.event.trigger("ajaxSend", [xhr, s]);
+			trigger("ajaxSend", [xhr, s]);
 		}
 
 		// Wait for a response to come back
@@ -464,24 +464,24 @@
 		function success(){
 			// If a local callback was specified, fire it and pass it the data
 			if ( s.success ) {
-				s.success( data, status );
+				s.success.call( callbackContext, data, status );
 			}
 
 			// Fire the global callback
 			if ( s.global ) {
-				jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+				trigger( "ajaxSuccess", [xhr, s] );
 			}
 		}
 
 		function complete(){
 			// Process result
 			if ( s.complete ) {
-				s.complete(xhr, status);
+				s.complete.call( callbackContext, xhr, status);
 			}
 
 			// The request was completed
 			if ( s.global ) {
-				jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+				trigger( "ajaxComplete", [xhr, s] );
 			}
 
 			// Handle the global AJAX counter
@@ -489,6 +489,10 @@
 				jQuery.event.trigger( "ajaxStop" );
 			}
 		}
+		
+		function trigger(type, args){
+			(s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
+		}
 
 		// return XMLHttpRequest to allow aborting the request etc.
 		return xhr;
@@ -497,12 +501,12 @@
 	handleError: function( s, xhr, status, e ) {
 		// If a local callback was specified, fire it
 		if ( s.error ) {
-			s.error( xhr, status, e );
+			s.error.call( s.context || window, xhr, status, e );
 		}
 
 		// Fire the global callback
 		if ( s.global ) {
-			jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+			(s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
 		}
 	},
 
Index: test/unit/ajax.js
===================================================================
--- test/unit/ajax.js	(revision 6562)
+++ test/unit/ajax.js	(working copy)
@@ -70,6 +70,44 @@
 	});
 });
 
+test("Ajax events with context", function() {
+	expect(6);
+	
+	stop();
+	var context = {};
+	
+	function event(e){
+		equals( this, context, e.type );
+	}
+
+	function callback(){
+		equals( this, context, "context is preserved on callback" );
+	}
+	
+	jQuery('#foo').add(context)
+			.ajaxSend(event)
+			.ajaxComplete(event)
+			.ajaxError(event)
+			.ajaxSuccess(event);
+
+	jQuery.ajax({
+		url: url("data/name.html"),
+		beforeSend: callback,
+		success: callback,
+		error: callback,
+		complete:function(){
+			callback.call(this);
+			setTimeout(proceed, 300);
+		},
+		context:context
+	});
+	
+	function proceed(){
+		jQuery('#foo').add(context).unbind();
+		start();
+	}
+});
+
 test("jQuery.ajax() - disabled globals", function() {
 	expect( 3 );
 	stop();
@@ -284,19 +322,20 @@
 
 test("ajax cache", function () {
 	expect(18);
+	
 	stop();
 
 	var count = 0;
 
 	jQuery("#firstp").bind("ajaxSuccess", function (e, xml, s) {
 		var re = /_=(.*?)(&|$)/g;
-	var oldOne = null;
+		var oldOne = null;
 		for (var i = 0; i < 6; i++) {
-	  var ret = re.exec(s.url);
+			var ret = re.exec(s.url);
 			if (!ret) {
 				break;
 			}
-	  oldOne = ret[1];
+			oldOne = ret[1];
 		}
 		equals(i, 1, "Test to make sure only one 'no-cache' parameter is there");
 		ok(oldOne != "tobereplaced555", "Test to be sure parameter (if it was there) was replaced");
@@ -953,4 +992,4 @@
 
 }
 
-//}
+//}
\ No newline at end of file
