oAjaxAttacher = function (linkSource, linkTarget, responseFilter, submitResponseFilter, idsToClasses, jsResponseCallbacks, responseTriggers, triggerHandler, loadingHTML) { 
	this.linkSource = linkSource;
	this.linkTarget = linkTarget;
	this.responseFilter = responseFilter;
	this.submitResponseFilter = submitResponseFilter;
	this.idsToClasses = idsToClasses;
	this.jsResponseCallbacks = jsResponseCallbacks;
	this.responseTriggers = responseTriggers;
	this.triggerHandler = triggerHandler;
	this.loadingHTML = loadingHTML;
};
attachLinksToTarget = function(scope,oOptions) {
	clickHandler = 
			function (event) {
				//Don't attach to links with the href '#' as they obviously are performing some js function that we'll interfere with
				if(this.href == this.baseURI + "#" || this.onclick) {
					return false;
				}
				event.data.targetLoading(event.data);
				jQuery.ajax({
					oOptions: event.data,
					url: this.href,
					dataType:"html",
					complete: function(res, status) {
						if ( status == "success" || status == "notmodified" ) { 
							var responseText = res.responseText;
							
							//Hide the link target to our manipulations to it do not look messy.
							this.oOptions.linkTarget.hide();
							
							//Store the response in a temporary jQuery object so we can more easily operate on it
							var temp = jQuery("<div/>").prepend(responseText.replace(/<script(.|\s)*?\/script>/g, ""));
							if(jQuery(this.oOptions.responseTriggers, temp).length) {
								this.oOptions.triggerHandler(temp, this.oOptions);
							}
							//Store classes to be preserved
							var storeClasses = new Array;
							var tempIdStorage;
							for(var i in this.oOptions.idsToClasses) {
								tempIdStorage = jQuery(this.oOptions.idsToClasses[i], temp);
								if(tempIdStorage.length) {
									storeClasses.push(tempIdStorage.attr("class"));
								}
							}
							//Filter the html response by the designated responseFilter.  If that element is not found, simply inject all the HTML
							if(jQuery(this.oOptions.responseFilter, temp).length) {
								this.oOptions.linkTarget.html(jQuery(this.oOptions.responseFilter, temp).html());
							}
							else {
								this.oOptions.linkTarget.html(temp.html());
							}
							//preserve classes if any are stored
							if(storeClasses.length > 0) {
								//clear existing classes
								this.oOptions.linkTarget.attr({ "class" : ""});
								//add classes
								for(var i in storeClasses) {
									this.oOptions.linkTarget.addClass(storeClasses[i]);
								}
							}
							//call other js functions that may need to responsd to the new html
							for(var i in this.oOptions.jsResponseCallbacks) {
								this.oOptions.jsResponseCallbacks[i]();
							}
							this.oOptions.linkTarget.show("fast");
							attachLinksToTarget(this.oOptions.linkTarget, this.oOptions);	
							attachSubmitsToTarget(this.oOptions.linkTarget,this.oOptions);
						}
						else {
							this.oOptions.linkTarget.html("Error loading page, please try again later.")
						}
					}
				});
			return false;
			}
			jQuery("a", scope).bind("click", oOptions, clickHandler)
		
}
attachSubmitsToTarget = function(scope, oOptions) {
	//var responseFilter = (responseFilter == null) ? this.submitResponseFilter : responseFilter;
		
		submitHandler =	function (event) {
				//special case for the file attachment module: return true so it can do its thing
				if(this.id == 'attach') {
					return true;
				}
				
				//Add our op value to the form since drupal needs it
				jQuery(this).after('<input type="hidden" name="op" value="' + this.value +'">');
				jQuery(this.form).ajaxSubmit({ oOptions:event.data, success: 
					function (responseText, statusText, form, self) {
						
						if (statusText == "success") {
							//Hide the link target to our manipulations to it do not look messy.
							self.oOptions.linkTarget.hide();
							
							//Store the response in a temporary jQuery object so we can more easily operate on it
							var temp = jQuery("<div/>").prepend(responseText.replace(/<script(.|\s)*?\/script>/g, ""));
							if(jQuery(self.oOptions.responseTriggers, temp).length) {
								self.oOptions.triggerHandler(temp, self.oOptions);
							}
							
							//Store classes to be preserved
							var storeClasses = new Array;
							var tempIdStorage;
							for(var i in self.oOptions.idsToClasses) {
								tempIdStorage = jQuery(self.oOptions.idsToClasses[i], temp);
								if(tempIdStorage.length) {
									storeClasses.push(tempIdStorage.attr("class"));
								}
							}
							
							//Filter the html response by the designated responseFilter.  If that element is not found, simply inject all the HTML
							if(jQuery(self.oOptions.submitResponseFilter, temp).length) {
								self.oOptions.linkTarget.html(jQuery(self.oOptions.submitResponseFilter, temp).html());
							}
							else if(jQuery(self.oOptions.responseFilter, temp).length) {
								self.oOptions.linkTarget.html(jQuery(self.oOptions.responseFilter, temp).html());
							}
							
							else {
								self.oOptions.linkTarget.html(temp.html());
							}
							
							//preserve classes if any are stored
							if(storeClasses.length > 0) {
								//clear existing classes
								self.oOptions.linkTarget.attr({"class":""});
								//add classes
								for(var i in storeClasses) {
									self.oOptions.linkTarget.addClass(storeClasses[i]);
								}
							}
							
							//call other js functions that may need to responsd to the new html
							for(var i in self.oOptions.jsResponseCallbacks) {
								self.oOptions.jsResponseCallbacks[i]();
							}
							self.oOptions.linkTarget.show("fast");
							attachLinksToTarget(self.oOptions.linkTarget, self.oOptions);	
							attachSubmitsToTarget(self.oOptions.linkTarget, self.oOptions);
							
						}
						else {
							self.oOptions.linkTarget.html("Error submitting form, please try again later.")
						}
					}
				});
				event.data.targetLoading(event.data);
				return false;
			}
		jQuery(":submit", scope).bind("click", oOptions, submitHandler)
}

oAjaxAttacher.prototype.targetLoading = function(oOptions) {
	this.linkTarget.html(oOptions.loadingHTML);
}